< Summary

Line coverage
40%
Covered lines: 4311
Uncovered lines: 6278
Coverable lines: 10589
Total lines: 15049
Line coverage: 40.7%
Branch coverage
37%
Covered branches: 5142
Total branches: 13836
Branch coverage: 37.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: get_AllowedToDependOnAllocationState()0%120%
File 1: get_Kind()0%80%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%10%
File 1: Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()100%1100%
File 1: .ctor(...)100%1100%
File 1: GetContext(...)100%1100%
File 1: VisitOneStatement(...)33.33%2440%
File 1: VisitTopLevelFrameExpression(...)100%1100%
File 1: DesugarFunctionsInFrameClause(...)100%1100%
File 1: FrameArrowToObjectSet(...)5%2014.28%
File 1: VisitExpression(...)50%457.14%
File 1: VisitOneExpression(...)5.55%728.88%
File 1: DiscoverBestBounds_MultipleVars(...)0%80%
File 1: DiscoverBestBounds_MultipleVars_AllowReordering(...)0%520%
File 1: DiscoverAllBounds_Aux_MultipleVars(...)0%80%
File 1: DiscoverAllBounds_SingleVar(...)100%10%
File 1: DiscoverAllBounds_Aux_SingleVar(...)0%2040%
File 1: DiscoverBoundsFunctionCallExpr(...)0%80%
File 1: NormalizedConjuncts()0%1720%
File 1: SanitizeForBoundDiscovery(...)0%1080%
File 1: IsMonotonic(...)0%240%
File 2: ResolveNamesAndInferTypes(...)100%8100%
File 2: ResolveNamesAndInferTypesForOneDeclarationInitial(...)62.5%1657.57%
File 2: ResolveNamesAndInferTypesForOneDeclaration(...)66.66%3656.52%
File 2: EagerAddAssignableConstraint(...)0%80%
File 2: AddAssignableConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddAssignableConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: PrintTypeConstraintState(...)12.5%3223.52%
File 2: SolveAllTypeConstraints()20%2043.47%
File 2: ResolveAttributes(...)91.66%2483.33%
File 2: ResolveExpression(...)38.79%61640.86%
File 2: ResolveTypeParameters(...)80%2082.35%
File 2: ConstrainSubtypeRelation(...)100%1100%
File 2: ConstrainTypeExprBool(...)100%1100%
File 2: ConstrainSubtypeRelation(...)100%1100%
File 2: ConstrainAssignable(...)78.57%2890.47%
File 2: ConstrainAssignableTypeArgs(...)92.85%2891.89%
File 2: ConstrainSubtypeRelation_Equal(...)87.5%3277.77%
File 2: ConstrainSubtypeRelation(...)100%24100%
File 2: ConstrainSubtypeRelation_Aux(...)91.66%2491.66%
File 2: DetermineRootLeaf(...)75.92%10870%
File 2: .ctor(...)100%1100%
File 2: AssignProxyAndHandleItsConstraints(...)50%477.77%
File 2: AssignProxyAndHandleItsConstraints_aux(...)67.39%9259.37%
File 2: ImposeSubtypingConstraint(...)80%4086.66%
File 2: ConstrainTypeHead_Recursive(...)41.66%1285.71%
File 2: ConstrainTypeHead(...)56.32%15870.58%
File 2: KeepConstraints(...)88.88%5483.33%
File 2: .ctor(...)100%1100%
File 2: ToString()0%80%
File 2: Confirm(...)62.5%102464.65%
File 2: ProxyWithNoSubTypeConstraint(...)100%2091.66%
File 2: CouldBeAnything()100%10%
File 2: FindCollectionType(...)16.66%3633.33%
File 2: .ctor(...)100%1100%
File 2: .ctor(...)100%1100%
File 2: PartiallySolveTypeConstraints(...)58.14%35663.26%
File 2: NewIntegerBasedProxy(...)100%1100%
File 2: ContainsAsTypeParameter(...)0%280%
File 2: AddAllProxies(...)100%8100%
File 2: ProcessAssignable(...)70.83%4859.37%
File 2: ConvertAssignableToSubtypeConstraints(...)100%28100%
File 2: TightenUpEquatable(...)80%2082.35%
File 2: ProcessOneSubtypingConstraintAndItsSubs(...)90%4096.15%
File 2: ProcessFullStrength_SubDirection(...)90%20100%
File 2: ProcessFullStrength_SuperDirection(...)100%20100%
File 2: AssignKnownEnd(...)57.14%5674.35%
File 2: AssignKnownEndsFullstrength(...)18.33%6033.33%
File 2: AssignKnownEndsFullstrength_SubDirection(...)80.76%5284.21%
File 2: CloseOverAssignableRhss(...)71.42%2876.47%
File 2: HasApplicableNullableRefTypeConstraint(...)50%1258.33%
File 2: HasApplicableNullableRefTypeConstraint_SubDirection(...)100%12100%
File 2: HasApplicableNullableRefTypeConstraint_SubDirection_aux(...)40%2061.53%
File 2: AssignKnownEndsFullstrength_SuperDirection(...)86.66%6084.61%
File 2: Reaches(...)50%477.77%
File 2: Reaches_aux(...)83.33%3687.5%
File 2: ResolveClassMemberBodiesInitial(...)33.33%2442.1%
File 2: ResolveClassMemberBodies(...)45.45%4454.76%
File 2: ResolveCtorTypes(...)41.66%2462.5%
File 2: ResolveCtorSignature(...)100%4100%
File 2: AddDatatypeDependencyEdge(...)66.66%12100%
File 2: ResolveFrameExpressionTopLevel(...)100%1100%
File 2: ResolveFrameExpression(...)10.71%2850%
File 2: ResolveIterator(...)0%480%
File 2: CheckIsLvalue(...)23.07%5238.7%
File 2: ResolveBlockStatement(...)37.5%1647.05%
File 2: ResolveStatementWithLabels(...)12.5%1625%
File 2: ResolveAlternatives(...)0%280%
File 2: ResolveCallStmt(...)50%7263.33%
File 2: ResolveActualParameters(...)37.09%12452.13%
File 2: GetLocationInformation(...)83.33%12100%
File 2: ResolveDotSuffix_Type(...)0%520%
File 2: CreateResolver_IdentifierExpr(...)78.12%3277.77%
File 2: ResolveStatement(...)39.36%56441.83%
File 2: ResolveLoopSpecificationComponents(...)58.33%2471.42%
File 2: ResolveParameterDefaultValues(...)44.44%3641.66%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: .ctor(...)100%10%
File 2: ResolveTypeLenient(...)63.15%15261.26%
File 2: FillInTypeArguments(...)81.25%3290.9%
File 2: TypeConstraintsIncludeProxy(...)100%1100%
File 2: TypeConstraintsIncludeProxy_Aux(...)22.22%3644%
File 2: ResolveTypeRhs(...)19.11%13624%
File 2: ResolveMember(...)60.41%4856.52%
File 2: PartiallyResolveTypeForMemberSelection(...)45.91%19643.57%
File 2: GetBaseTypeFromProxy(...)80.55%3672.72%
File 2: GetBaseTypeFromProxy_Eq(...)100%4100%
File 2: GetBaseTypeFromProxy_EqAux(...)12.5%3221.73%
File 2: GetRelatedTypeProxies(...)65.62%6464%
File 2: JoinOfAllSubtypes(...)55.55%7275.67%
File 2: MeetOfAllSupertypes(...)64.06%6464.44%
File 2: CheckVariance(...)53.94%7668.62%
File 2: ConstrainToIntegerType(...)100%4100%
File 2: ResolveDatatypeUpdate(...)0%440%
File 2: DesugarDatatypeUpdate(...)0%320%
File 2: ResolveNameSegment(...)100%1100%
File 2: ResolveNameSegment(...)35.93%12838.14%
File 2: ResolveDatatypeConstructor(...)50%2853.33%
File 2: ResolveNameSegment_Type(...)71.42%2877.41%
File 2: ResolveDotSuffix(...)35.36%16441.6%
File 2: CheckForAmbiguityInShadowedImportedModule(...)50%833.33%
File 2: NameConflictsWithModuleContents(...)0%200%
File 2: ResolveExprDotCall(...)45.83%9661.76%
File 2: ResolveApplySuffix(...)25.8%12430.69%
File 2: ResolveDatatypeValue(...)46.87%3270%
File 2: ResolveFunctionCallExpr(...)0%600%
File 2: ResolveReceiver(...)0%80%
File 2: ResolveSeqSelectExpr(...)87.5%1696.77%
File 3: get_Options()100%1100%
File 3: .ctor(...)100%176.92%
File 3: get_Reporter()100%1100%
File 3: get_TypeConstraintErrorsToBeReported()100%1100%
File 3: RevealedInScope(...)0%40%
File 3: VisibleInScope(...)100%4100%
File 3: FreshTempVarName(...)0%40%
File 3: Create(...)0%200%
File 3: Name(...)0%80%
File 3: ModuleNames(...)0%80%
File 3: Create(...)0%40%
File 3: Equals(...)0%80%
File 3: GetHashCode(...)0%40%
File 3: get_WhatKind()100%10%
File 3: .ctor(...)100%10%
File 3: Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.TopLevelDecl>.get_Pool()100%10%
File 3: ModuleNames()100%10%
File 3: Create(...)0%40%
File 3: Equals(...)100%10%
File 3: GetHashCode(...)100%10%
File 3: get_WhatKind()100%10%
File 3: .ctor(...)100%10%
File 3: Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.MemberDecl>.get_Pool()100%10%
File 3: ModuleNames()100%10%
File 3: .ctor(...)100%8100%
File 3: AddRotateMember(...)100%1100%
File 3: ObjectInvariant()100%10%
File 3: AsValuetypeDecl(...)75%885.71%
File 3: CheckDupModuleNames(...)62.5%1676.47%
File 3: ResolveProgram(...)65.54%29674.18%
File 3: ResolveValuetypeDecls()87.5%1678.57%
File 3: ResolveModuleDefinition(...)29.16%4856.25%
File 3: ResolveModuleExport(...)10.89%31214.54%
File 3: CheckModuleExportConsistency(...)3.57%5610%
File 3: .ctor(...)100%1100%
File 3: BindName(...)50%487.5%
File 3: TryLookup(...)100%10%
File 3: TryLookupFilter(...)0%120%
File 3: get_ModuleList()100%10%
File 3: SubBindings(...)100%10%
File 3: BindModuleNames(...)28.12%6424.56%
File 3: ShortenPrefix(...)100%10%
File 3: BindModuleName_LiteralModuleDecl(...)0%160%
File 3: ResolveQualifiedModuleIdRootRefines(...)100%10%
File 3: ResolveQualifiedModuleIdRootImport(...)0%120%
File 3: ResolveQualifiedModuleIdRootAbstract(...)0%120%
File 3: ProcessDependenciesDefinition(...)20%4024.13%
File 3: ProcessDependencies(...)20%2030%
File 3: ModuleNotFoundErrorMessage(...)0%40%
File 3: EquivIfPresent(...)50%480%
File 3: MergeSignature(...)60%4064.28%
File 3: ResolveOpenedImports(...)50%3244.44%
File 3: ResolveAlias(...)0%40%
File 3: ResolveOpenedImportsWorker(...)0%720%
File 3: RegisterTopLevelDecls(...)68.88%18074.68%
File 3: RegisterMembers(...)26.47%6814.49%
File 3: RegisterByMethod(...)0%80%
File 3: MakeAbstractSignature(...)0%200%
File 3: CloneDeclaration(...)0%40%
File 3: ResolveModuleQualifiedId(...)0%240%
File 3: ResolveExport(...)0%360%
File 3: RevealAllInScope(...)100%24100%
File 3: ResolveTopLevelDecls_Signatures(...)57.69%10461.03%
File 3: .cctor()100%10%
File 3: ResolveTopLevelDecls_Core(...)51.01%78848.44%
File 3: FillInPostConditionsAndBodiesOfPrefixLemmas(...)2.94%682.5%
File 3: CheckIsOkayWithoutRHS(...)0%240%
File 3: ResolveClassMembers_Pass1(...)50%6447.61%
File 3: CheckForUnnecessaryEqualitySupportDeclarations(...)25%837.5%
File 3: CheckParameterDefaultValuesAreCompilable(...)12.5%1637.5%
File 3: ReportCallGraphCycleError(...)100%10%
File 3: ReportCycleError(...)100%10%
File 3: MaxBV(...)100%10%
File 3: MaxBV(...)100%10%
File 3: FigureOutNativeType(...)0%9340%
File 3: CheckOlderParameters(...)0%200%
File 3: CheckExpression(...)100%1100%
File 3: CheckExpression(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneExpr(...)25%1630.76%
File 3: VisitOneStmt(...)50%2445.45%
File 3: CheckForFuelAdjustments(...)3.57%5614.81%
File 3: .ctor(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)100%1100%
File 3: Invert(...)0%80%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%1040%
File 3: KNatMismatchError(...)0%120%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%360%
File 3: VisitOneStmt(...)0%80%
File 3: ExtremePredicateChecks(...)100%10%
File 3: .ctor(...)100%10%
File 3: VisitOneStmt(...)0%160%
File 3: VisitOneExpr(...)0%80%
File 3: ExtremeLemmaChecks(...)100%10%
File 3: ExtremeLemmaChecks(...)0%40%
File 3: CheckTypeCharacteristics_Stmt(...)100%1100%
File 3: CheckTypeCharacteristics_Expr(...)100%1100%
File 3: CheckTypeCharacteristics_Type(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)62.5%11264.44%
File 3: VisitOneExpr(...)52.7%14840%
File 3: VisitType(...)60%6077.77%
File 3: CheckTypeInstantiation(...)50%1272.72%
File 3: CheckCharacteristics(...)46.66%6042.3%
File 3: TypeEqualityErrorMessageHint(...)0%120%
File 3: CanCompareWith(...)6.25%3220%
File 3: ComputeGhostInterest(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)75%866.66%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)10%2015%
File 3: .ctor(...)100%1100%
File 3: CheckInit(...)100%10%
File 3: CheckInit(...)0%160%
File 3: VisitExpr(...)100%10%
File 3: VisitOneExpr(...)0%200%
File 3: LiberalRHSVisit(...)0%480%
File 3: IsThisDotField(...)0%40%
File 3: IsCollectionOperator(...)0%200%
File 3: InferRequiredEqualitySupport(...)48.43%6472.22%
File 3: ResolveParentTraitTypes(...)4.54%4429.62%
File 3: RegisterInheritedMembers(...)12.5%9615.94%
File 3: ResolveClassMemberTypes(...)33.33%4835.29%
File 3: InheritedTraitMembers(...)7.89%15210%
File 3: CheckOverride_FunctionParameters(...)0%240%
File 3: CheckOverride_MethodParameters(...)0%200%
File 3: CheckOverride_TypeParameters(...)0%320%
File 3: CheckOverride_ResolvedParameters(...)0%600%
File 3: SccStratosphereCheck(...)42.85%2864%
File 3: ComputeGroundingCtor(...)88.88%3691.66%
File 3: CheckCanBeConstructed(...)40.27%7273.46%
File 3: DetermineEqualitySupport(...)60.48%12461.53%
File 3: IsRecognizedAttribute(...)0%1000%
File 3: ScopePushAndReport(...)100%1100%
File 3: ScopePushAndReport(...)50%855.55%
File 3: ResolveFunctionSignature(...)62.5%1677.77%
File 3: DisallowNonGhostFieldSpecifiers(...)0%80%
File 3: ResolveMethodSignature(...)87.5%1687.5%
File 3: ResolveIteratorSignature(...)0%320%
File 3: ObjectInvariant()100%10%
File 3: .ctor(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: ResolvedArrayType(...)100%1100%
File 3: FillInDefaultLoopDecreases(...)4.67%2144.13%
File 3: VarDotMethod(...)100%10%
File 3: makeTemp(...)100%10%
File 3: EnsureSupportsErrorHandling(...)0%400%
File 3: CheckLocalityUpdates(...)0%520%
File 3: CheckLocalityUpdatesLhs(...)0%80%
File 3: .ctor(...)100%10%
File 3: ToString()0%40%
File 3: FindAllMembers(...)100%4100%
File 3: GetThisType(...)50%866.66%
File 3: GetReceiverType(...)100%10%
File 3: ResolveDominatingLabelInExpr(...)0%120%
File 3: VarDotFunction(...)100%10%
File 3: LetPatIn(...)100%10%
File 3: LetVarIn(...)100%10%
File 3: ResolveLetOrFailExpr(...)0%40%
File 3: SelectAppropriateArrowTypeForFunction(...)100%10%
File 3: SelectAppropriateArrowType(...)0%80%
File 3: ConstrainToIntegerType(...)100%1100%
File 3: ResolveNestedMatchExpr(...)100%1100%
File 3: ResolveCasePattern(...)0%1000%
File 3: FillInDefaultValueExpressions()50%471.42%
File 3: FillInDefaultValueExpression(...)0%80%
File 3: .ctor(...)100%10%
File 3: Substitute(...)0%40%
File 3: BuildTypeArgumentSubstitute(...)62.5%1673.33%
File 3: AddParentTypeParameterSubstitutions(...)70%2075%
File 3: GhostPrefix(...)50%4100%
File 3: GetSignatureExt(...)0%80%
File 3: GetSignature(...)100%10%
File 3: GetImpliedTypeConstraint(...)100%1100%
File 3: GetImpliedTypeConstraint(...)50%1660%
File 3: FreeVariables(...)0%680%
File 3: .cctor()100%1100%
File 3: get_Msg()0%160%
File 3: .ctor(...)100%1100%
File 3: ResolveOp(...)86.19%21091.8%
File 3: CollectFriendlyCallsInExtremeLemmaSpecification(...)0%40%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%560%
File 4: get_IsPrefixPredicate()100%1100%
File 4: get_IsExtremePredicate()100%10%
File 4: get_IsPrefixDeclaration()50%4100%
File 4: .ctor(...)100%1100%
File 4: Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()100%1100%
File 4: get_reporter()100%10%
File 4: .ctor(...)100%1100%
File 4: GetContext(...)100%1100%
File 4: VisitOneDeclaration(...)55%4046.66%
File 4: VisitField(...)50%457.14%
File 4: VisitOneStatement(...)50%444.44%
File 4: PostVisitOneStatement(...)58.33%2452.17%
File 4: PostVisitOneExpression(...)34.39%34634.9%
File 4: VisitExtendedPattern(...)100%8100%
File 4: IsDetermined(...)100%4100%
File 4: CheckTypeIsDetermined(...)100%8100%
File 4: CheckTypeArgsContainNoOrdinal(...)50%4100%
File 4: CheckContainsNoOrdinal(...)50%471.42%

File(s)

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/BoundsDiscovery.cs

#LineLine coverage
 1//-----------------------------------------------------------------------------
 2//
 3// Copyright by the contributors to the Dafny Project
 4// SPDX-License-Identifier: MIT
 5//
 6//-----------------------------------------------------------------------------
 7using System.Collections.Generic;
 8using System.Linq;
 9using System.Diagnostics.Contracts;
 10using Microsoft.Boogie;
 11
 12namespace Microsoft.Dafny {
 13  public partial class Resolver {
 14    private class BoundsDiscoveryVisitor : ASTVisitor<BoundsDiscoveryVisitor.BoundsDiscoveryContext> {
 15      public class BoundsDiscoveryContext : IASTVisitorContext {
 16        private readonly IASTVisitorContext astVisitorContext;
 17        readonly bool inLambdaExpression;
 18
 19        public bool AllowedToDependOnAllocationState =>
 020          !(astVisitorContext is Function or ConstantField or RedirectingTypeDecl || inLambdaExpression);
 21
 22        public string Kind {
 023          get {
 24            // assumes context denotes a lambda expression, redirecting type, or member declaration
 025            if (inLambdaExpression) {
 026              return "lambda expression";
 27            }
 28            string kind;
 029            if (astVisitorContext is RedirectingTypeDecl redirectingTypeDecl) {
 030              kind = redirectingTypeDecl.WhatKind;
 031            } else {
 032              var memberDecl = (MemberDecl)astVisitorContext;
 033              kind = memberDecl.WhatKind;
 034            }
 035            return $"{kind} definition";
 036          }
 37        }
 38
 1451639        public BoundsDiscoveryContext(IASTVisitorContext astVisitorContext) {
 725840          this.astVisitorContext = astVisitorContext;
 725841          this.inLambdaExpression = false;
 725842        }
 43
 44        /// <summary>
 45        /// This constructor is used to say that, within parentContext, the context is inside a lambda
 46        /// expression.
 47        /// </summary>
 048        public BoundsDiscoveryContext(BoundsDiscoveryContext parentContext, LambdaExpr lambdaExpr) {
 049          this.astVisitorContext = parentContext.astVisitorContext;
 050          this.inLambdaExpression = true;
 051        }
 52
 476853        ModuleDefinition IASTVisitorContext.EnclosingModule => astVisitorContext.EnclosingModule;
 54      }
 55
 56      private readonly ErrorReporter reporter;
 57
 171658      public BoundsDiscoveryVisitor(ErrorReporter reporter) {
 85859        this.reporter = reporter;
 85860      }
 61
 725862      public override BoundsDiscoveryContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostconditi
 725863        return new BoundsDiscoveryContext(astVisitorContext);
 725864      }
 65
 29728666      protected override bool VisitOneStatement(Statement stmt, BoundsDiscoveryContext context) {
 29728667        if (stmt is ForallStmt forallStmt) {
 068          forallStmt.Bounds = DiscoverBestBounds_MultipleVars(forallStmt.BoundVars, forallStmt.Range, true);
 069          if (forallStmt.Body == null) {
 070            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, forallStmt.Tok, "note, this forall statement 
 071          }
 29728672        } else if (stmt is AssignSuchThatStmt assignSuchThatStmt) {
 073          if (assignSuchThatStmt.AssumeToken == null) {
 074            var varLhss = new List<IVariable>();
 075            foreach (var lhs in assignSuchThatStmt.Lhss) {
 076              var ide = (IdentifierExpr)lhs.Resolved;  // successful resolution implies all LHS's are IdentifierExpr's
 077              varLhss.Add(ide.Var);
 078            }
 079            assignSuchThatStmt.Bounds = DiscoverBestBounds_MultipleVars(varLhss, assignSuchThatStmt.Expr, true);
 080          }
 29847881        } else if (stmt is OneBodyLoopStmt oneBodyLoopStmt) {
 119282          oneBodyLoopStmt.ComputeBodySurrogate(reporter);
 119283        }
 84
 29728685        return base.VisitOneStatement(stmt, context);
 29728686      }
 87
 1088      public override void VisitTopLevelFrameExpression(FrameExpression frameExpression, BoundsDiscoveryContext context)
 1089        DesugarFunctionsInFrameClause(frameExpression);
 1090        base.VisitTopLevelFrameExpression(frameExpression, context);
 1091      }
 92
 1093      void DesugarFunctionsInFrameClause(FrameExpression frameExpression) {
 1094        frameExpression.DesugaredExpression = FrameArrowToObjectSet(frameExpression.E);
 1095      }
 96
 97      /// <summary>
 98      /// The motivation for this method is to convert a reads-clause frame expression "f.reads" into a set.
 99      /// More generally, if the given expression "e" has type "X ~> collection<Y>", for some list of type X,
 100      /// some reference type Y, and "collection" being "set", "iset", "seq", or "multiset", then this method
 101      /// returns an expression of type "set<Y>" denoting
 102      ///
 103      ///     UNION x: X :: e(x)                      // e.g., UNION x: X :: f.reads(x)
 104      ///
 105      /// For example, if "e" is an expression "f.reads" of type "X ~> set<object>", then the expression
 106      /// returned is the union of "f.reads(x)" over all inputs "x" to "f".
 107      ///
 108      /// If the type of "e" is not of the form "X ~> collection<Y>" as stated above, then this method simply
 109      /// returns the given "e".
 110      ///
 111      /// Dafny does not have a UNION comprehension, so the expression returned has the form
 112      ///
 113      ///     { obj: Y | exists x: X :: obj in e(x) }
 114      ///
 115      /// which in Dafny notation is written
 116      ///
 117      ///     set x: X, obj: Y | obj in e(x) :: obj
 118      ///
 119      /// Note, since Y is a reference type and there is, at any one time, only a finite number of references,
 120      /// the result type is finite.
 121      ///
 122      /// Note: A pending improvement would be to limit the range of the set comprehension to the values for x
 123      /// that satisfy e's precondition.
 124      /// </summary>
 10125      public static Expression FrameArrowToObjectSet(Expression e) {
 126        Contract.Requires(e != null);
 10127        var arrowType = e.Type.AsArrowType;
 20128        if (arrowType == null) {
 10129          return e;
 130        }
 0131        var collectionType = arrowType.Result.AsCollectionType;
 0132        if (collectionType == null || collectionType.NormalizeExpand() is MapType) {
 0133          return e;
 134        }
 0135        var elementType = collectionType.Arg; // "elementType" is called "Y" in the description of this method, above
 0136        if (!elementType.IsRefType) {
 0137          return e;
 138        }
 139
 0140        var boundVarDecls = new List<BoundVar>();
 0141        var boundVarUses = new List<Expression>();
 0142        var i = 0;
 0143        foreach (var functionArgumentType in arrowType.Args) {
 0144          var bv = new BoundVar(e.tok, $"_x{i}", functionArgumentType);
 0145          boundVarDecls.Add(bv);
 0146          boundVarUses.Add(new IdentifierExpr(e.tok, bv.Name) { Type = bv.Type, Var = bv });
 0147          i++;
 0148        }
 0149        var objVar = new BoundVar(e.tok, "_obj", elementType);
 0150        var objUse = new IdentifierExpr(e.tok, objVar.Name) { Type = objVar.Type, Var = objVar };
 0151        boundVarDecls.Add(objVar);
 152
 0153        var collection = new ApplyExpr(e.tok, e, boundVarUses, e.tok) {
 0154          Type = collectionType
 0155        };
 0156        var resolvedOpcode = collectionType.ResolvedOpcodeForIn;
 157
 0158        var inCollection = new BinaryExpr(e.tok, BinaryExpr.Opcode.In, objUse, collection) {
 0159          ResolvedOp = resolvedOpcode,
 0160          Type = Type.Bool
 0161        };
 162
 0163        var attributes = new Attributes("_reads", new List<Expression>(), null);
 0164        return new SetComprehension(e.tok, e.RangeToken, true, boundVarDecls, inCollection, objUse, attributes) {
 0165          Type = new SetType(true, elementType)
 0166        };
 10167      }
 168
 1531980169      protected override void VisitExpression(Expression expr, BoundsDiscoveryContext context) {
 1531980170        if (expr is LambdaExpr lambdaExpr) {
 0171          lambdaExpr.Reads.Iter(DesugarFunctionsInFrameClause);
 172
 173          // Make the context more specific when visiting inside a lambda expression
 0174          context = new BoundsDiscoveryContext(context, lambdaExpr);
 0175        }
 1531980176        base.VisitExpression(expr, context);
 1531980177      }
 178
 1531980179      protected override bool VisitOneExpression(Expression expr, BoundsDiscoveryContext context) {
 1531980180        if (expr is ComprehensionExpr and not LambdaExpr) {
 0181          var e = (ComprehensionExpr)expr;
 182          // apply bounds discovery to quantifiers, finite sets, and finite maps
 0183          Expression whereToLookForBounds = null;
 0184          var polarity = true;
 0185          if (e is QuantifierExpr quantifierExpr) {
 0186            whereToLookForBounds = quantifierExpr.LogicalBody();
 0187            polarity = quantifierExpr is ExistsExpr;
 0188          } else if (e is SetComprehension setComprehension) {
 0189            whereToLookForBounds = setComprehension.Range;
 0190          } else if (e is MapComprehension) {
 0191            whereToLookForBounds = e.Range;
 0192          } else {
 0193            Contract.Assert(false);  // otherwise, unexpected ComprehensionExpr
 0194          }
 0195          if (whereToLookForBounds != null) {
 0196            e.Bounds = DiscoverBestBounds_MultipleVars_AllowReordering(e.BoundVars, whereToLookForBounds, polarity);
 0197            if (2 <= reporter.Options.Allocated && !context.AllowedToDependOnAllocationState) {
 0198              foreach (var bv in ComprehensionExpr.BoundedPool.MissingBounds(e.BoundVars, e.Bounds,
 0199                         ComprehensionExpr.BoundedPool.PoolVirtues.IndependentOfAlloc)) {
 0200                var how = Attributes.Contains(e.Attributes, "_reads") ? "(implicitly by using a function in a reads clau
 0201                var message =
 0202                  $"a {e.WhatKind} involved in a {context.Kind} {how}is not allowed to depend on the set of allocated re
 0203                  $" but values of '{bv.Name}' (of type '{bv.Type}') may contain references";
 0204                if (bv.Type.IsTypeParameter || bv.Type.IsAbstractType) {
 0205                  message += $" (perhaps declare its type as '{bv.Type}(!new)')";
 0206                }
 0207                message += " (see documentation for 'older' parameters)";
 0208                reporter.Error(MessageSource.Resolver, e, message);
 0209              }
 0210            }
 211
 0212            if ((e as SetComprehension)?.Finite == true || (e as MapComprehension)?.Finite == true) {
 213              // the comprehension had better produce a finite set
 0214              if (e.Type.HasFinitePossibleValues) {
 215                // This means the set is finite, regardless of if the Range is bounded.  So, we don't give any error her
 216                // However, if this expression is used in a non-ghost context (which is not yet known at this stage of
 217                // resolution), the resolver will generate an error about that later.
 0218              } else {
 219                // we cannot be sure that the set/map really is finite
 0220                foreach (var bv in ComprehensionExpr.BoundedPool.MissingBounds(e.BoundVars, e.Bounds, ComprehensionExpr.
 0221                  reporter.Error(MessageSource.Resolver, e,
 0222                    "the result of a {0} must be finite, but Dafny's heuristics can't figure out how to produce a bounde
 0223                    e.WhatKind, bv.Name);
 0224                }
 0225              }
 0226            }
 0227          }
 228
 0229        }
 230
 1531980231        return base.VisitOneExpression(expr, context);
 1531980232      }
 233    }
 234
 235    /// <summary>
 236    /// For a list of variables "bvars", returns a list of best bounds for each respective variable.
 237    /// If no bound is found for a variable "v", then the bound for "v" in the returned list is set to "null".
 238    /// </summary>
 239    public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars<VT>(List<VT> bvars, Expression exp
 0240      bool polarity) where VT : IVariable {
 241      Contract.Requires(bvars != null);
 242      Contract.Requires(expr != null);
 243      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 0244      foreach (var bv in bvars) {
 0245        var c = GetImpliedTypeConstraint(bv, bv.Type);
 0246        expr = polarity ? Expression.CreateAnd(c, expr) : Expression.CreateImplies(c, expr);
 0247      }
 0248      var bests = DiscoverAllBounds_Aux_MultipleVars(bvars, expr, polarity);
 0249      return bests;
 0250    }
 251
 252    public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars_AllowReordering<VT>(List<VT> bvars
 0253      bool polarity) where VT : IVariable {
 254      Contract.Requires(bvars != null);
 255      Contract.Requires(expr != null);
 256      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 0257      var bounds = DiscoverBestBounds_MultipleVars(bvars, expr, polarity);
 0258      if (bvars.Count > 1) {
 259        // It may be helpful to try all permutations (or, better yet, to use an algorithm that keeps track of the depend
 260        // and discovers good bounds more efficiently). However, all permutations would be expensive. Therefore, we try 
 261        // other permutation, namely the reversal "bvars". This covers the important case where there are two bound vari
 262        // that work out in the opposite order. It also covers one more case for the (probably rare) case of there being
 263        // than two bound variables.
 0264        var bvarsMissyElliott = new List<VT>(bvars);  // make a copy
 0265        bvarsMissyElliott.Reverse();  // and then flip it and reverse it, Ti esrever dna ti pilf nwod gnaht ym tup I
 0266        var boundsMissyElliott = DiscoverBestBounds_MultipleVars(bvarsMissyElliott, expr, polarity);
 267        // Figure out which one seems best
 0268        var meBetter = 0;
 0269        for (int i = 0; i < bvars.Count; i++) {
 0270          var orig = bounds[i];
 0271          var me = boundsMissyElliott[i];
 0272          if (orig == null && me != null) {
 0273            meBetter = 1; break; // end game
 0274          } else if (orig != null && me == null) {
 0275            meBetter = -1; break; // end game
 0276          } else if (orig != null && me != null) {
 0277            if ((orig.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite) != 0) { meBetter--; }
 0278            if ((orig.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Enumerable) != 0) { meBetter--; }
 0279            if ((me.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite) != 0) { meBetter++; }
 0280            if ((me.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Enumerable) != 0) { meBetter++; }
 0281          }
 0282        }
 0283        if (meBetter > 0) {
 284          // yes, this reordering seems to have been better
 0285          bvars.Reverse();
 0286          return boundsMissyElliott;
 287        }
 0288      }
 0289      return bounds;
 0290    }
 291
 292    private static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_Aux_MultipleVars<VT>(List<VT> bvars, Expression
 0293      bool polarity) where VT : IVariable {
 294      Contract.Requires(bvars != null);
 295      Contract.Requires(expr != null);
 296      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 297      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>().Count == bvars.Count);
 0298      var knownBounds = new List<ComprehensionExpr.BoundedPool>();
 0299      for (var j = 0; j < bvars.Count; j++) {
 0300        knownBounds.Add(null);
 0301      }
 302      // Note, in the following loop, it's important to go backwards, because DiscoverAllBounds_Aux_SingleVar assumes "k
 303      // filled in for higher-indexed variables.
 0304      for (var j = bvars.Count; 0 <= --j;) {
 0305        var bounds = DiscoverAllBounds_Aux_SingleVar(bvars, j, expr, polarity, knownBounds);
 0306        knownBounds[j] = ComprehensionExpr.BoundedPool.GetBest(bounds);
 307#if DEBUG_PRINT
 308        if (knownBounds[j] is ComprehensionExpr.IntBoundedPool) {
 309          var ib = (ComprehensionExpr.IntBoundedPool)knownBounds[j];
 310          var lo = ib.LowerBound == null ? "" : Printer.ExprToString(ib.LowerBound);
 311          var hi = ib.UpperBound == null ? "" : Printer.ExprToString(ib.UpperBound);
 312          Console.WriteLine("DEBUG: Bound for var {3}, {0}:  {1} .. {2}", bvars[j].Name, lo, hi, j);
 313        } else if (knownBounds[j] is ComprehensionExpr.SetBoundedPool) {
 314          Console.WriteLine("DEBUG: Bound for var {2}, {0}:  in {1}", bvars[j].Name, Printer.ExprToString(((Comprehensio
 315        } else {
 316          Console.WriteLine("DEBUG: Bound for var {2}, {0}:  {1}", bvars[j].Name, knownBounds[j], j);
 317        }
 318#endif
 0319      }
 0320      return knownBounds;
 0321    }
 322
 0323    public static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_SingleVar<VT>(VT v, Expression expr) where VT : 
 0324      expr = Expression.CreateAnd(GetImpliedTypeConstraint(v, v.Type), expr);
 0325      return DiscoverAllBounds_Aux_SingleVar(new List<VT> { v }, 0, expr, true, new List<ComprehensionExpr.BoundedPool>(
 0326    }
 327
 328    /// <summary>
 329    /// Returns a list of (possibly partial) bounds for "bvars[j]", each of which can be written without mentioning any 
 330    /// that is not bounded.
 331    /// </summary>
 332    private static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_Aux_SingleVar<VT>(List<VT> bvars, int j, Expres
 0333      bool polarity, List<ComprehensionExpr.BoundedPool> knownBounds) where VT : IVariable {
 334      Contract.Requires(bvars != null);
 335      Contract.Requires(0 <= j && j < bvars.Count);
 336      Contract.Requires(expr != null);
 337      Contract.Requires(knownBounds != null);
 338      Contract.Requires(knownBounds.Count == bvars.Count);
 0339      var bv = bvars[j];
 0340      var bounds = new List<ComprehensionExpr.BoundedPool>();
 341
 342      // Maybe the type itself gives a bound
 0343      if (bv.Type.IsBoolType) {
 0344        bounds.Add(new ComprehensionExpr.BoolBoundedPool());
 0345      } else if (bv.Type.IsCharType) {
 0346        bounds.Add(new ComprehensionExpr.CharBoundedPool());
 0347      } else if (bv.Type.IsDatatype && bv.Type.AsDatatype.HasFinitePossibleValues) {
 0348        bounds.Add(new ComprehensionExpr.DatatypeBoundedPool(bv.Type.AsDatatype));
 0349      } else if (bv.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0350        bounds.Add(new AssignSuchThatStmt.WiggleWaggleBound());
 0351      } else if (!bv.Type.MayInvolveReferences) {
 0352        bounds.Add(new ComprehensionExpr.AllocFreeBoundedPool(bv.Type));
 0353      }
 354
 355      // Go through the conjuncts of the range expression to look for bounds.
 0356      foreach (var conjunct in NormalizedConjuncts(expr, polarity)) {
 0357        if (conjunct is IdentifierExpr) {
 0358          var ide = (IdentifierExpr)conjunct;
 0359          if (ide.Var == (IVariable)bv) {
 0360            Contract.Assert(bv.Type.IsBoolType);
 0361            bounds.Add(new ComprehensionExpr.ExactBoundedPool(Expression.CreateBoolLiteral(Token.NoToken, true)));
 0362          }
 0363          continue;
 364        }
 0365        if (conjunct is UnaryOpExpr || conjunct is OldExpr) {
 366          // we also consider a unary expression sitting immediately inside an old
 0367          var unary = conjunct as UnaryOpExpr ?? ((OldExpr)conjunct).E.Resolved as UnaryOpExpr;
 0368          if (unary != null) {
 0369            var ide = unary.E.Resolved as IdentifierExpr;
 0370            if (ide != null && ide.Var == (IVariable)bv) {
 0371              if (unary.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot) {
 0372                bounds.Add(new ComprehensionExpr.ExactBoundedPool(Expression.CreateBoolLiteral(Token.NoToken, false)));
 0373              } else if (unary.ResolvedOp == UnaryOpExpr.ResolvedOpcode.Allocated) {
 0374                bounds.Add(new ComprehensionExpr.ExplicitAllocatedBoundedPool());
 0375              }
 0376            }
 0377          }
 0378          continue;
 379        }
 0380        if (conjunct is FunctionCallExpr functionCallExpr) {
 0381          DiscoverBoundsFunctionCallExpr(functionCallExpr, bv, bounds);
 0382          continue;
 383        }
 0384        var c = conjunct as BinaryExpr;
 0385        if (c == null) {
 386          // other than what we already covered above, we only know what to do with binary expressions
 0387          continue;
 388        }
 0389        var e0 = c.E0;
 0390        var e1 = c.E1;
 0391        int whereIsBv = SanitizeForBoundDiscovery(bvars, j, c.ResolvedOp, knownBounds, ref e0, ref e1);
 0392        if (whereIsBv < 0) {
 0393          continue;
 394        }
 0395        switch (c.ResolvedOp) {
 396          case BinaryExpr.ResolvedOpcode.InSet:
 0397            if (whereIsBv == 0) {
 0398              bounds.Add(new ComprehensionExpr.SetBoundedPool(e1, e0.Type, e1.Type.AsSetType.Arg, e1.Type.AsSetType.Fini
 0399            }
 0400            break;
 401          case BinaryExpr.ResolvedOpcode.Subset:
 0402            if (whereIsBv == 0) {
 0403              bounds.Add(new ComprehensionExpr.SubSetBoundedPool(e1, e1.Type.AsSetType.Finite));
 0404            } else {
 0405              bounds.Add(new ComprehensionExpr.SuperSetBoundedPool(e0));
 0406            }
 0407            break;
 408          case BinaryExpr.ResolvedOpcode.InMultiSet:
 0409            if (whereIsBv == 0) {
 0410              bounds.Add(new ComprehensionExpr.MultiSetBoundedPool(e1, e0.Type, e1.Type.AsMultiSetType.Arg));
 0411            }
 0412            break;
 413          case BinaryExpr.ResolvedOpcode.InSeq:
 0414            if (whereIsBv == 0 && e1.Type.AsSeqType is { } seqType) {
 0415              bounds.Add(new ComprehensionExpr.SeqBoundedPool(e1, e0.Type, seqType.Arg));
 0416            }
 0417            break;
 418          case BinaryExpr.ResolvedOpcode.InMap:
 0419            if (whereIsBv == 0) {
 0420              bounds.Add(new ComprehensionExpr.MapBoundedPool(e1, e0.Type, e1.Type.AsMapType.Arg, e1.Type.AsMapType.Fini
 0421            }
 0422            break;
 423          case BinaryExpr.ResolvedOpcode.EqCommon:
 424          case BinaryExpr.ResolvedOpcode.SetEq:
 425          case BinaryExpr.ResolvedOpcode.SeqEq:
 426          case BinaryExpr.ResolvedOpcode.MultiSetEq:
 427          case BinaryExpr.ResolvedOpcode.MapEq:
 0428            var otherOperand = whereIsBv == 0 ? e1 : e0;
 0429            bounds.Add(new ComprehensionExpr.ExactBoundedPool(otherOperand));
 0430            break;
 431          case BinaryExpr.ResolvedOpcode.Gt:
 432          case BinaryExpr.ResolvedOpcode.Ge:
 0433            Contract.Assert(false);
 0434            throw new cce.UnreachableException(); // promised by postconditions of NormalizedConjunct
 435          case BinaryExpr.ResolvedOpcode.Lt:
 0436            if (e0.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0437              if (whereIsBv == 0) {
 438                // bv < E
 0439                bounds.Add(new ComprehensionExpr.IntBoundedPool(null, e1));
 0440              } else {
 441                // E < bv
 0442                bounds.Add(new ComprehensionExpr.IntBoundedPool(Expression.CreateIncrement(e0, 1), null));
 0443              }
 0444            }
 0445            break;
 446          case BinaryExpr.ResolvedOpcode.Le:
 0447            if (e0.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0448              if (whereIsBv == 0) {
 449                // bv <= E
 0450                bounds.Add(new ComprehensionExpr.IntBoundedPool(null, Expression.CreateIncrement(e1, 1)));
 0451              } else {
 452                // E <= bv
 0453                bounds.Add(new ComprehensionExpr.IntBoundedPool(e0, null));
 0454              }
 0455            }
 0456            break;
 457          case BinaryExpr.ResolvedOpcode.RankLt:
 0458            if (whereIsBv == 0) {
 0459              bounds.Add(new ComprehensionExpr.DatatypeInclusionBoundedPool(e0.Type.IsIndDatatype));
 0460            }
 0461            break;
 462          case BinaryExpr.ResolvedOpcode.RankGt:
 0463            if (whereIsBv == 1) {
 0464              bounds.Add(new ComprehensionExpr.DatatypeInclusionBoundedPool(e1.Type.IsIndDatatype));
 0465            }
 0466            break;
 467          default:
 0468            break;
 469        }
 0470      }
 0471      return bounds;
 0472    }
 473
 474    private static void DiscoverBoundsFunctionCallExpr<VT>(FunctionCallExpr fce, VT boundVariable, List<ComprehensionExp
 0475      where VT : IVariable {
 476      Contract.Requires(fce != null);
 477      Contract.Requires(boundVariable != null);
 478      Contract.Requires(bounds != null);
 479
 0480      var formals = fce.Function.Formals;
 0481      Contract.Assert(formals.Count == fce.Args.Count);
 0482      if (LinqExtender.Zip(formals, fce.Args).Any(t => t.Item1.IsOlder && t.Item2.Resolved is IdentifierExpr ide && ide.
 0483        bounds.Add(new ComprehensionExpr.OlderBoundedPool());
 0484        return;
 485      }
 0486    }
 487
 488    /// <summary>
 489    /// Returns all conjuncts of "expr" in "polarity" positions.  That is, if "polarity" is "true", then
 490    /// returns the conjuncts of "expr" in positive positions; else, returns the conjuncts of "expr" in
 491    /// negative positions.  The method considers a canonical-like form of the expression that pushes
 492    /// negations inwards far enough that one can determine what the result is going to be (so, almost
 493    /// a negation normal form).
 494    /// As a convenience, arithmetic inequalities are rewritten so that the negation of an arithmetic
 495    /// inequality is never returned and the comparisons > and >= are never returned; the negation of
 496    /// a common equality or disequality is rewritten analogously.
 497    /// Requires "expr" to be successfully resolved.
 498    /// Ensures that what is returned is not a ConcreteSyntaxExpression.
 499    /// </summary>
 0500    static IEnumerable<Expression> NormalizedConjuncts(Expression expr, bool polarity) {
 501      // We consider 5 cases.  To describe them, define P(e)=Conjuncts(e,true) and N(e)=Conjuncts(e,false).
 502      //   *  X ==> Y    is treated as a shorthand for !X || Y, and so is described by the remaining cases
 503      //   *  X && Y     P(_) = P(X),P(Y)    and    N(_) = !(X && Y)
 504      //   *  X || Y     P(_) = (X || Y)     and    N(_) = N(X),N(Y)
 505      //   *  !X         P(_) = N(X)         and    N(_) = P(X)
 506      //   *  else       P(_) = else         and    N(_) = !else
 507      // So for ==>, we have:
 508      //   *  X ==> Y    P(_) = P(!X || Y) = (!X || Y) = (X ==> Y)
 509      //                 N(_) = N(!X || Y) = N(!X),N(Y) = P(X),N(Y)
 0510      expr = expr.Resolved;
 511
 512      // Binary expressions
 0513      var b = expr as BinaryExpr;
 0514      if (b != null) {
 0515        bool breakDownFurther = false;
 0516        bool p0 = polarity;
 0517        switch (b.ResolvedOp) {
 518          case BinaryExpr.ResolvedOpcode.And:
 0519            breakDownFurther = polarity;
 0520            break;
 521          case BinaryExpr.ResolvedOpcode.Or:
 0522            breakDownFurther = !polarity;
 0523            break;
 524          case BinaryExpr.ResolvedOpcode.Imp:
 0525            breakDownFurther = !polarity;
 0526            p0 = !p0;
 0527            break;
 528          default:
 0529            break;
 530        }
 0531        if (breakDownFurther) {
 0532          foreach (var c in NormalizedConjuncts(b.E0, p0)) {
 0533            yield return c;
 0534          }
 0535          foreach (var c in NormalizedConjuncts(b.E1, polarity)) {
 0536            yield return c;
 0537          }
 0538          yield break;
 539        }
 0540      }
 541
 542      // Unary expression
 0543      var u = expr as UnaryOpExpr;
 0544      if (u != null && u.Op == UnaryOpExpr.Opcode.Not) {
 0545        foreach (var c in NormalizedConjuncts(u.E, !polarity)) {
 0546          yield return c;
 0547        }
 0548        yield break;
 549      }
 550
 551      // no other case applied, so return the expression or its negation, but first clean it up a little
 0552      b = expr as BinaryExpr;
 0553      if (b != null) {
 554        BinaryExpr.Opcode newOp;
 555        BinaryExpr.ResolvedOpcode newROp;
 556        bool swapOperands;
 0557        switch (b.ResolvedOp) {
 558          case BinaryExpr.ResolvedOpcode.Gt:  // A > B         yield polarity ? (B < A) : (A <= B);
 0559            newOp = polarity ? BinaryExpr.Opcode.Lt : BinaryExpr.Opcode.Le;
 0560            newROp = polarity ? BinaryExpr.ResolvedOpcode.Lt : BinaryExpr.ResolvedOpcode.Le;
 0561            swapOperands = polarity;
 0562            break;
 563          case BinaryExpr.ResolvedOpcode.Ge:  // A >= B        yield polarity ? (B <= A) : (A < B);
 0564            newOp = polarity ? BinaryExpr.Opcode.Le : BinaryExpr.Opcode.Lt;
 0565            newROp = polarity ? BinaryExpr.ResolvedOpcode.Le : BinaryExpr.ResolvedOpcode.Lt;
 0566            swapOperands = polarity;
 0567            break;
 568          case BinaryExpr.ResolvedOpcode.Le:  // A <= B        yield polarity ? (A <= B) : (B < A);
 0569            newOp = polarity ? BinaryExpr.Opcode.Le : BinaryExpr.Opcode.Lt;
 0570            newROp = polarity ? BinaryExpr.ResolvedOpcode.Le : BinaryExpr.ResolvedOpcode.Lt;
 0571            swapOperands = !polarity;
 0572            break;
 573          case BinaryExpr.ResolvedOpcode.Lt:  // A < B         yield polarity ? (A < B) : (B <= A);
 0574            newOp = polarity ? BinaryExpr.Opcode.Lt : BinaryExpr.Opcode.Le;
 0575            newROp = polarity ? BinaryExpr.ResolvedOpcode.Lt : BinaryExpr.ResolvedOpcode.Le;
 0576            swapOperands = !polarity;
 0577            break;
 578          case BinaryExpr.ResolvedOpcode.EqCommon:  // A == B         yield polarity ? (A == B) : (A != B);
 0579            newOp = polarity ? BinaryExpr.Opcode.Eq : BinaryExpr.Opcode.Neq;
 0580            newROp = polarity ? BinaryExpr.ResolvedOpcode.EqCommon : BinaryExpr.ResolvedOpcode.NeqCommon;
 0581            swapOperands = false;
 0582            break;
 583          case BinaryExpr.ResolvedOpcode.NeqCommon:  // A != B         yield polarity ? (A != B) : (A == B);
 0584            newOp = polarity ? BinaryExpr.Opcode.Neq : BinaryExpr.Opcode.Eq;
 0585            newROp = polarity ? BinaryExpr.ResolvedOpcode.NeqCommon : BinaryExpr.ResolvedOpcode.EqCommon;
 0586            swapOperands = false;
 0587            break;
 588          case BinaryExpr.ResolvedOpcode.NotInSet:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0589            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0590            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInSet : BinaryExpr.ResolvedOpcode.InSet;
 0591            swapOperands = false;
 0592            break;
 593          case BinaryExpr.ResolvedOpcode.NotInSeq:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0594            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0595            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInSeq : BinaryExpr.ResolvedOpcode.InSeq;
 0596            swapOperands = false;
 0597            break;
 598          case BinaryExpr.ResolvedOpcode.NotInMultiSet:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0599            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0600            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInMultiSet : BinaryExpr.ResolvedOpcode.InMultiSet;
 0601            swapOperands = false;
 0602            break;
 603          case BinaryExpr.ResolvedOpcode.NotInMap:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0604            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0605            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInMap : BinaryExpr.ResolvedOpcode.InMap;
 0606            swapOperands = false;
 0607            break;
 608          default:
 0609            goto JUST_RETURN_IT;
 610        }
 0611        if (newROp != b.ResolvedOp || swapOperands) {
 0612          b = new BinaryExpr(b.tok, newOp, swapOperands ? b.E1 : b.E0, swapOperands ? b.E0 : b.E1);
 0613          b.ResolvedOp = newROp;
 0614          b.Type = Type.Bool;
 0615          yield return b;
 0616          yield break;
 617        }
 0618      }
 0619    JUST_RETURN_IT:;
 0620      if (polarity) {
 0621        yield return expr;
 0622      } else {
 0623        expr = new UnaryOpExpr(expr.tok, UnaryOpExpr.Opcode.Not, expr);
 0624        expr.Type = Type.Bool;
 0625        yield return expr;
 0626      }
 0627    }
 628
 629    /// <summary>
 630    /// If the return value is negative, the resulting "e0" and "e1" should not be used.
 631    /// Otherwise, the following is true on return:
 632    /// The new "e0 op e1" is equivalent to the old "e0 op e1".
 633    /// One of "e0" and "e1" is the identifier "boundVars[bvi]"; the return value is either 0 or 1, and indicates which.
 634    /// The other of "e0" and "e1" is an expression whose free variables are not among "boundVars[bvi..]".
 635    /// Ensures that the resulting "e0" and "e1" are not ConcreteSyntaxExpression's.
 636    /// </summary>
 637    static int SanitizeForBoundDiscovery<VT>(List<VT> boundVars, int bvi, BinaryExpr.ResolvedOpcode op,
 638      List<ComprehensionExpr.BoundedPool> knownBounds,
 0639      ref Expression e0, ref Expression e1) where VT : IVariable {
 640      Contract.Requires(boundVars != null);
 641      Contract.Requires(0 <= bvi && bvi < boundVars.Count);
 642      Contract.Requires(knownBounds != null);
 643      Contract.Requires(knownBounds.Count == boundVars.Count);
 644      Contract.Requires(e0 != null);
 645      Contract.Requires(e1 != null);
 646      Contract.Ensures(Contract.Result<int>() < 2);
 647      Contract.Ensures(!(Contract.ValueAtReturn(out e0) is ConcreteSyntaxExpression));
 648      Contract.Ensures(!(Contract.ValueAtReturn(out e1) is ConcreteSyntaxExpression));
 649
 0650      IVariable bv = boundVars[bvi];
 0651      e0 = e0.Resolved;
 0652      e1 = e1.Resolved;
 653
 654      // make an initial assessment of where bv is; to continue, we need bv to appear in exactly one operand
 0655      var fv0 = FreeVariables(e0);
 0656      var fv1 = FreeVariables(e1);
 657      Expression thisSide;
 658      Expression thatSide;
 659      int whereIsBv;
 0660      if (fv0.Contains(bv)) {
 0661        if (fv1.Contains(bv)) {
 0662          return -1;
 663        }
 0664        whereIsBv = 0;
 0665        thisSide = e0;
 0666        thatSide = e1;
 0667      } else if (fv1.Contains(bv)) {
 0668        whereIsBv = 1;
 0669        thisSide = e1;
 0670        thatSide = e0;
 0671      } else {
 0672        return -1;
 673      }
 674
 675      // Next, clean up the side where bv is by adjusting both sides of the expression
 0676      switch (op) {
 677        case BinaryExpr.ResolvedOpcode.EqCommon:
 678        case BinaryExpr.ResolvedOpcode.NeqCommon:
 679        case BinaryExpr.ResolvedOpcode.Gt:
 680        case BinaryExpr.ResolvedOpcode.Ge:
 681        case BinaryExpr.ResolvedOpcode.Le:
 682        case BinaryExpr.ResolvedOpcode.Lt:
 683          // Repeatedly move additive or subtractive terms from thisSide to thatSide
 0684          while (true) {
 0685            var bin = thisSide as BinaryExpr;
 0686            if (bin == null) {
 0687              break; // done simplifying
 688
 0689            } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Add) {
 690              // Change "A+B op C" into either "A op C-B" or "B op C-A", depending on where we find bv among A and B.
 0691              if (!FreeVariables(bin.E1).Contains(bv)) {
 0692                thisSide = bin.E0.Resolved;
 0693                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, thatSide, bin.E1);
 0694              } else if (!FreeVariables(bin.E0).Contains(bv)) {
 0695                thisSide = bin.E1.Resolved;
 0696                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, thatSide, bin.E0);
 0697              } else {
 0698                break; // done simplifying
 699              }
 0700              ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Sub;
 0701              thatSide.Type = bin.Type;
 702
 0703            } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Sub) {
 704              // Change "A-B op C" in a similar way.
 0705              if (!FreeVariables(bin.E1).Contains(bv)) {
 706                // change to "A op C+B"
 0707                thisSide = bin.E0.Resolved;
 0708                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Add, thatSide, bin.E1);
 0709                ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Add;
 0710              } else if (!FreeVariables(bin.E0).Contains(bv)) {
 711                // In principle, change to "-B op C-A" and then to "B dualOp A-C".  But since we don't want
 712                // to change "op", we instead end with "A-C op B" and switch the mapping of thisSide/thatSide
 713                // to e0/e1 (by inverting "whereIsBv").
 0714                thisSide = bin.E1.Resolved;
 0715                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, bin.E0, thatSide);
 0716                ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Sub;
 0717                whereIsBv = 1 - whereIsBv;
 0718              } else {
 0719                break; // done simplifying
 720              }
 0721              thatSide.Type = bin.Type;
 722
 0723            } else {
 0724              break; // done simplifying
 725            }
 0726          }
 0727          break;
 728
 729        default:
 0730          break;
 731      }
 732      // our transformation above maintained the following invariant:
 0733      Contract.Assert(!FreeVariables(thatSide).Contains(bv));
 734
 735      // Now, see if the interesting side is simply bv itself
 0736      if (thisSide is IdentifierExpr && ((IdentifierExpr)thisSide).Var == bv) {
 737        // we're cool
 0738      } else {
 739        // no, the situation is more complicated than we care to understand
 0740        return -1;
 741      }
 742
 743      // Finally, check the bound variables of "thatSide". We allow "thatSide" to
 744      // depend on bound variables that are listed before "bv" (that is, a bound variable
 745      // "boundVars[k]" where "k < bvi"). By construction, "thatSide" does not depend
 746      // on "bv". Generally, for any bound variable "bj" that is listed after "bv"
 747      // (that is, "bj" is some "boundVars[j]" where "bvi < j"), we do not allow
 748      // "thatSide" to depend on "bv", but there is an important exception:
 749      // If
 750      //   *  "op" makes "thatSide" denote an integer upper bound on "bv" (or, analogously,
 751      //      a integer lower bound),
 752      //   *  "thatSide" depends on "bj",
 753      //   *  "thatSide" is monotonic in "bj",
 754      //   *  "bj" has a known integer upper bound "u",
 755      //   *  "u" does not depend on "bv" or any bound variable listed after "bv"
 756      //      (from the way we're constructing bounds, we already know that "u"
 757      //      does not depend on "bj" or any bound variable listed after "bj")
 758      // then we can substitute "u" for "bj" in "thatSide".
 759      // By going from right to left, we can make the rule above slightly more
 760      // liberal by considering a cascade of substitutions.
 0761      var fvThatSide = FreeVariables(thatSide);
 0762      for (int j = boundVars.Count; bvi + 1 <= --j;) {
 0763        if (fvThatSide.Contains(boundVars[j])) {
 0764          if (knownBounds[j] is ComprehensionExpr.IntBoundedPool) {
 0765            var jBounds = (ComprehensionExpr.IntBoundedPool)knownBounds[j];
 0766            Expression u = null;
 0767            if (op == BinaryExpr.ResolvedOpcode.Lt || op == BinaryExpr.ResolvedOpcode.Le) {
 0768              u = whereIsBv == 0 ? jBounds.UpperBound : jBounds.LowerBound;
 0769            } else if (op == BinaryExpr.ResolvedOpcode.Gt || op == BinaryExpr.ResolvedOpcode.Ge) {
 0770              u = whereIsBv == 0 ? jBounds.LowerBound : jBounds.UpperBound;
 0771            }
 0772            if (u != null && !FreeVariables(u).Contains(bv) && IsMonotonic(u, boundVars[j], true)) {
 0773              thatSide = Translator.Substitute(thatSide, boundVars[j], u);
 0774              fvThatSide = FreeVariables(thatSide);
 0775              continue;
 776            }
 0777          }
 0778          return -1; // forget about "bv OP thatSide"
 779        }
 0780      }
 781
 782      // As we return, also return the adjusted sides
 0783      if (whereIsBv == 0) {
 0784        e0 = thisSide;
 0785        e1 = thatSide;
 0786      } else {
 0787        e0 = thatSide;
 0788        e1 = thisSide;
 0789      }
 0790      return whereIsBv;
 0791    }
 792
 793    /// <summary>
 794    /// If "position", then returns "true" if "x" occurs only positively in "expr".
 795    /// If "!position", then returns "true" if "x" occurs only negatively in "expr".
 796    /// </summary>
 0797    public static bool IsMonotonic(Expression expr, IVariable x, bool position) {
 798      Contract.Requires(expr != null && expr.Type != null);
 799      Contract.Requires(x != null);
 800
 0801      if (expr is IdentifierExpr identifierExpr) {
 0802        return identifierExpr.Var != x || position;
 0803      } else if (expr is BinaryExpr binaryExpr) {
 0804        if (binaryExpr.ResolvedOp == BinaryExpr.ResolvedOpcode.Add) {
 0805          return IsMonotonic(binaryExpr.E0, x, position) && IsMonotonic(binaryExpr.E1, x, position);
 0806        } else if (binaryExpr.ResolvedOp == BinaryExpr.ResolvedOpcode.Sub) {
 0807          return IsMonotonic(binaryExpr.E0, x, position) && IsMonotonic(binaryExpr.E1, x, !position);
 808        }
 0809      }
 0810      return !FreeVariables(expr).Contains(x);
 0811    }
 812  }
 813}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/NameResolutionAndTypeInference.cs

#LineLine coverage
 1#define TI_DEBUG_PRINT
 2//-----------------------------------------------------------------------------
 3//
 4// Copyright (C) Microsoft Corporation.  All Rights Reserved.
 5// Copyright by the contributors to the Dafny Project
 6// SPDX-License-Identifier: MIT
 7//
 8//-----------------------------------------------------------------------------
 9using System;
 10using System.Collections.Generic;
 11using System.Linq;
 12using System.Numerics;
 13using System.Diagnostics.Contracts;
 14using System.IO;
 15using System.Reflection;
 16using JetBrains.Annotations;
 17using Microsoft.BaseTypes;
 18using Microsoft.Boogie;
 19using Microsoft.CodeAnalysis.CSharp.Syntax;
 20using Microsoft.Dafny.Plugins;
 21using static Microsoft.Dafny.ErrorRegistry;
 22
 23namespace Microsoft.Dafny {
 24  public partial class Resolver {
 25    /// <summary>
 26    /// There are two rounds of name resolution + type inference. The "initialRound" parameter says which one to do.
 27    /// </summary>
 177628    void ResolveNamesAndInferTypes(List<TopLevelDecl> declarations, bool initialRound) {
 1932629      foreach (TopLevelDecl topd in declarations) {
 466630        Contract.Assert(topd != null);
 466631        Contract.Assert(VisibleInScope(topd));
 466632        Contract.Assert(AllTypeConstraints.Count == 0);
 466633        Contract.Assert(currentClass == null);
 34
 466635        allTypeParameters.PushMarker();
 466636        ResolveTypeParameters(topd.TypeArgs, !initialRound, topd);
 37
 699938        if (initialRound) {
 233339          ResolveNamesAndInferTypesForOneDeclarationInitial(topd);
 466640        } else {
 233341          ResolveNamesAndInferTypesForOneDeclaration(topd);
 233342        }
 43
 466644        allTypeParameters.PopMarker();
 45
 466646        Contract.Assert(AllTypeConstraints.Count == 0);
 466647        Contract.Assert(currentClass == null);
 466648      }
 177649    }
 50
 51    /// <summary>
 52    /// Assumes type parameters of "topd" have already been pushed.
 53    /// </summary>
 233354    void ResolveNamesAndInferTypesForOneDeclarationInitial(TopLevelDecl topd) {
 233355      if (topd is NewtypeDecl newtypeDecl) {
 56        // this check can be done only after it has been determined that the redirected types do not involve cycles
 057        AddXConstraint(newtypeDecl.tok, "NumericType", newtypeDecl.BaseType, "newtypes must be based on some numeric typ
 58        // type check the constraint, if any
 059        if (newtypeDecl.Var != null) {
 060          Contract.Assert(object.ReferenceEquals(newtypeDecl.Var.Type, newtypeDecl.BaseType));  // follows from NewtypeD
 061          Contract.Assert(newtypeDecl.Constraint != null);  // follows from NewtypeDecl invariant
 62
 063          scope.PushMarker();
 064          scope.AllowInstance = false;
 065          var added = scope.Push(newtypeDecl.Var.Name, newtypeDecl.Var);
 066          Contract.Assert(added == Scope<IVariable>.PushResult.Success);
 067          ResolveExpression(newtypeDecl.Constraint, new ResolutionContext(new CodeContextWrapper(newtypeDecl, true), fal
 068          Contract.Assert(newtypeDecl.Constraint.Type != null);  // follows from postcondition of ResolveExpression
 069          ConstrainTypeExprBool(newtypeDecl.Constraint, "newtype constraint must be of type bool (instead got {0})");
 070          scope.PopMarker();
 071        }
 072        SolveAllTypeConstraints();
 73
 294574      } else if (topd is SubsetTypeDecl subsetTypeDecl) {
 75        // type check the constraint
 61276        Contract.Assert(object.ReferenceEquals(subsetTypeDecl.Var.Type, subsetTypeDecl.Rhs)); // follows from SubsetType
 61277        Contract.Assert(subsetTypeDecl.Constraint != null); // follows from SubsetTypeDecl invariant
 61278        scope.PushMarker();
 61279        scope.AllowInstance = false;
 61280        var added = scope.Push(subsetTypeDecl.Var.Name, subsetTypeDecl.Var);
 61281        Contract.Assert(added == Scope<IVariable>.PushResult.Success);
 61282        ResolveExpression(subsetTypeDecl.Constraint, new ResolutionContext(new CodeContextWrapper(subsetTypeDecl, true),
 61283        Contract.Assert(subsetTypeDecl.Constraint.Type != null); // follows from postcondition of ResolveExpression
 61284        ConstrainTypeExprBool(subsetTypeDecl.Constraint, "subset-type constraint must be of type bool (instead got {0})"
 61285        scope.PopMarker();
 61286        SolveAllTypeConstraints();
 61287      }
 88
 405489      if (topd is TopLevelDeclWithMembers cl) {
 172190        ResolveClassMemberBodiesInitial(cl);
 172191      }
 233392    }
 93
 233394    void ResolveNamesAndInferTypesForOneDeclaration(TopLevelDecl topd) {
 233395      if (topd is NewtypeDecl newtypeDecl) {
 096        if (newtypeDecl.Witness != null) {
 097          var codeContext = new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Ghost);
 098          scope.PushMarker();
 099          scope.AllowInstance = false;
 0100          ResolveExpression(newtypeDecl.Witness, new ResolutionContext(codeContext, false));
 0101          scope.PopMarker();
 0102          ConstrainSubtypeRelation(newtypeDecl.Var.Type, newtypeDecl.Witness.Type, newtypeDecl.Witness, "witness express
 0103        }
 0104        SolveAllTypeConstraints();
 105
 2945106      } else if (topd is SubsetTypeDecl subsetTypeDecl) {
 612107        if (subsetTypeDecl.Witness != null) {
 0108          var codeContext = new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.WitnessKind == SubsetTypeDecl.WKind.Gh
 0109          scope.PushMarker();
 0110          scope.AllowInstance = false;
 0111          ResolveExpression(subsetTypeDecl.Witness, new ResolutionContext(codeContext, false));
 0112          scope.PopMarker();
 0113          ConstrainSubtypeRelation(subsetTypeDecl.Var.Type, subsetTypeDecl.Witness.Type, subsetTypeDecl.Witness,
 0114            "witness expression must have type '{0}' (got '{1}')", subsetTypeDecl.Var.Type, subsetTypeDecl.Witness.Type)
 0115        }
 612116        SolveAllTypeConstraints();
 117
 2333118      } else if (topd is IteratorDecl iteratorDecl) {
 0119        ResolveIterator(iteratorDecl);
 120
 2248121      } else if (topd is DatatypeDecl dt) {
 122        // resolve any default parameters
 4617123        foreach (var ctor in dt.Ctors) {
 1012124          scope.PushMarker();
 1012125          scope.AllowInstance = false;
 1832126          ctor.Formals.ForEach(p => scope.Push(p.Name, p));
 1012127          ResolveAttributes(ctor, new ResolutionContext(new NoContext(topd.EnclosingModuleDefinition), false), true);
 1012128          ResolveParameterDefaultValues(ctor.Formals, ResolutionContext.FromCodeContext(dt));
 1012129          scope.PopMarker();
 1012130        }
 527131      }
 132
 4054133      if (topd is TopLevelDeclWithMembers cl) {
 1721134        ResolveClassMemberBodies(cl);
 1721135      }
 136
 137      // resolve attributes
 2333138      scope.PushMarker();
 2333139      Contract.Assert(currentClass == null);
 2333140      scope.AllowInstance = false;
 2333141      if (topd is IteratorDecl iter) {
 0142        iter.Ins.ForEach(p => scope.Push(p.Name, p));
 0143      }
 2333144      ResolveAttributes(topd, new ResolutionContext(new NoContext(topd.EnclosingModuleDefinition), false), true);
 2333145      scope.PopMarker();
 2333146    }
 147
 0148    void EagerAddAssignableConstraint(IToken tok, Type lhs, Type rhs, string errMsgFormat) {
 149      Contract.Requires(tok != null);
 150      Contract.Requires(lhs != null);
 151      Contract.Requires(rhs != null);
 152      Contract.Requires(errMsgFormat != null);
 0153      var lhsNormalized = lhs.Normalize();
 0154      var rhsNormalized = rhs.Normalize();
 0155      if (lhsNormalized is TypeProxy lhsProxy && !(rhsNormalized is TypeProxy)) {
 0156        Contract.Assert(lhsProxy.T == null); // otherwise, lhs.Normalize() above would have kept on going
 0157        AssignProxyAndHandleItsConstraints(lhsProxy, rhsNormalized, true);
 0158      } else {
 0159        AddAssignableConstraint(tok, lhs, rhs, errMsgFormat);
 0160      }
 0161    }
 229159162    public void AddAssignableConstraint(IToken tok, Type lhs, Type rhs, string errMsgFormat) {
 163      Contract.Requires(tok != null);
 164      Contract.Requires(lhs != null);
 165      Contract.Requires(rhs != null);
 166      Contract.Requires(errMsgFormat != null);
 229159167      AddXConstraint(tok, "Assignable", lhs, rhs, errMsgFormat);
 229159168    }
 92914169    private void AddXConstraint(IToken tok, string constraintName, Type type, string errMsgFormat) {
 170      Contract.Requires(tok != null);
 171      Contract.Requires(constraintName != null);
 172      Contract.Requires(type != null);
 173      Contract.Requires(errMsgFormat != null);
 92914174      var types = new Type[] { type };
 92914175      AllXConstraints.Add(new XConstraint(tok, constraintName, types, new TypeConstraint.ErrorMsgWithToken(tok, errMsgFo
 92914176    }
 15171177    void AddAssignableConstraint(IToken tok, Type lhs, Type rhs, TypeConstraint.ErrorMsg errMsg) {
 178      Contract.Requires(tok != null);
 179      Contract.Requires(lhs != null);
 180      Contract.Requires(rhs != null);
 181      Contract.Requires(errMsg != null);
 15171182      AddXConstraint(tok, "Assignable", lhs, rhs, errMsg);
 15171183    }
 6861184    private void AddXConstraint(IToken tok, string constraintName, Type type, TypeConstraint.ErrorMsg errMsg) {
 185      Contract.Requires(tok != null);
 186      Contract.Requires(constraintName != null);
 187      Contract.Requires(type != null);
 188      Contract.Requires(errMsg != null);
 6861189      var types = new Type[] { type };
 6861190      AllXConstraints.Add(new XConstraint(tok, constraintName, types, errMsg));
 6861191    }
 364885192    private void AddXConstraint(IToken tok, string constraintName, Type type0, Type type1, string errMsgFormat) {
 193      Contract.Requires(tok != null);
 194      Contract.Requires(constraintName != null);
 195      Contract.Requires(type0 != null);
 196      Contract.Requires(type1 != null);
 197      Contract.Requires(errMsgFormat != null);
 364885198      var types = new Type[] { type0, type1 };
 364885199      AllXConstraints.Add(new XConstraint(tok, constraintName, types, new TypeConstraint.ErrorMsgWithToken(tok, errMsgFo
 364885200    }
 53737201    private void AddXConstraint(IToken tok, string constraintName, Type type0, Type type1, TypeConstraint.ErrorMsg errMs
 202      Contract.Requires(tok != null);
 203      Contract.Requires(constraintName != null);
 204      Contract.Requires(type0 != null);
 205      Contract.Requires(type1 != null);
 206      Contract.Requires(errMsg != null);
 53737207      var types = new Type[] { type0, type1 };
 53737208      AllXConstraints.Add(new XConstraint(tok, constraintName, types, errMsg));
 53737209    }
 3495210    private void AddXConstraint(IToken tok, string constraintName, Type type, Expression expr0, Expression expr1, string
 211      Contract.Requires(tok != null);
 212      Contract.Requires(constraintName != null);
 213      Contract.Requires(type != null);
 214      Contract.Requires(expr0 != null);
 215      Contract.Requires(expr1 != null);
 216      Contract.Requires(errMsgFormat != null);
 3495217      var types = new Type[] { type };
 3495218      var exprs = new Expression[] { expr0, expr1 };
 3495219      AllXConstraints.Add(new XConstraintWithExprs(tok, constraintName, types, exprs, new TypeConstraint.ErrorMsgWithTok
 3495220    }
 221
 222    [System.Diagnostics.Conditional("TI_DEBUG_PRINT")]
 495489223    void PrintTypeConstraintState(int lbl) {
 990978224      if (!Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 495489225        return;
 226      }
 0227      Options.OutputWriter.WriteLine("DEBUG: ---------- type constraints ---------- {0} {1}", lbl, lbl == 0 && currentMe
 0228      foreach (var constraint in AllTypeConstraints) {
 0229        var super = constraint.Super.Normalize();
 0230        var sub = constraint.Sub.Normalize();
 0231        Options.OutputWriter.WriteLine("    {0} :> {1}", super is IntVarietiesSupertype ? "int-like" : super is RealVari
 0232      }
 0233      foreach (var xc in AllXConstraints) {
 0234        Options.OutputWriter.WriteLine("    {0}", xc);
 0235      }
 0236      Options.OutputWriter.WriteLine();
 0237      if (lbl % 2 == 1) {
 0238        Options.OutputWriter.WriteLine("DEBUG: --------------------------------------");
 0239      }
 495489240    }
 241
 242    /// <summary>
 243    /// Attempts to fully solve all type constraints.
 244    /// Upon failure, reports errors.
 245    /// Clears all constraints.
 246    /// </summary>
 27393247    public void SolveAllTypeConstraints() {
 27393248      PrintTypeConstraintState(0);
 27393249      PartiallySolveTypeConstraints(true);
 27393250      PrintTypeConstraintState(1);
 82179251      foreach (var constraint in AllTypeConstraints) {
 0252        if (Type.IsSupertype(constraint.Super, constraint.Sub)) {
 253          // unexpected condition -- PartiallySolveTypeConstraints is supposed to have continued until no more sub-typin
 0254          Contract.Assume(false, string.Format("DEBUG: Unexpectedly satisfied supertype relation ({0} :> {1}) |||| ", co
 0255        } else {
 0256          constraint.FlagAsError(this);
 0257        }
 0258      }
 82179259      foreach (var xc in AllXConstraints) {
 0260        if (xc.Confirm(this, true, out var convertedIntoOtherTypeConstraints, out var moreXConstraints)) {
 261          // unexpected condition -- PartiallySolveTypeConstraints is supposed to have continued until no more XConstrai
 0262          Contract.Assume(false, string.Format("DEBUG: Unexpectedly confirmed XConstraint: {0} |||| ", xc));
 0263        } else if (xc.CouldBeAnything()) {
 264          // suppress the error message; it will later be flagged as an underspecified type
 0265        } else {
 0266          xc.errorMsg.FlagAsError(this);
 0267        }
 0268      }
 27393269      TypeConstraint.ReportErrors(this, reporter);
 27393270      AllTypeConstraints.Clear();
 27393271      AllXConstraints.Clear();
 27393272    }
 273
 274    /// <summary>
 275    /// Adds type constraints for the expressions in the given attributes.
 276    ///
 277    /// If "solveConstraints" is "true", then the constraints are also solved. In this case, it is assumed on entry that
 278    /// prior type constraints. That is, the only type constraints being solved for are the ones in the given attributes
 279    /// </summary>
 626883280    public void ResolveAttributes(IAttributeBearingDeclaration attributeHost, ResolutionContext resolutionContext, bool 
 281      Contract.Requires(resolutionContext != null);
 282      Contract.Requires(attributeHost != null);
 283
 626883284      Contract.Assume(!solveConstraints || AllTypeConstraints.Count == 0);
 285
 286      // order does not matter much for resolution, so resolve them in reverse order
 1889307287      foreach (var attr in attributeHost.Attributes.AsEnumerable()) {
 2886288        if (attr is UserSuppliedAttributes) {
 0289          var usa = (UserSuppliedAttributes)attr;
 0290          usa.Recognized = IsRecognizedAttribute(usa, attributeHost);
 0291        }
 5772292        if (attr.Args != null) {
 15480293          foreach (var arg in attr.Args) {
 2274294            Contract.Assert(arg != null);
 2274295            ResolveExpression(arg, resolutionContext);
 2274296          }
 2886297        }
 2886298      }
 299
 636347300      if (solveConstraints) {
 9464301        SolveAllTypeConstraints();
 9464302      }
 626883303    }
 304
 305    /// <summary>
 306    /// "IsTwoState" implies that "old" and "fresh" expressions are allowed.
 307    /// </summary>
 1664489308    public void ResolveExpression(Expression expr, ResolutionContext resolutionContext) {
 309
 310#if TEST_TYPE_SYNONYM_TRANSPARENCY
 311      ResolveExpressionX(expr, resolutionContext);
 312      // For testing purposes, change the type of "expr" to a type synonym (mwo-ha-ha-ha!)
 313      var t = expr.Type;
 314      Contract.Assert(t != null);
 315      var sd = new TypeSynonymDecl(expr.tok, "type#synonym#transparency#test", new TypeParameter.TypeParameterCharacteri
 316        new List<TypeParameter>(), resolutionContext.CodeContext.EnclosingModule, t, null);
 317      var ts = new UserDefinedType(expr.tok, "type#synonym#transparency#test", sd, new List<Type>(), null);
 318      expr.DebugTest_ChangeType(ts);
 319    }
 320    public void ResolveExpressionX(Expression expr, ResolutionContext resolutionContext) {
 321#endif
 322      Contract.Requires(expr != null);
 323      Contract.Requires(resolutionContext != null);
 324      Contract.Ensures(expr.Type != null);
 2006319325      if (expr.Type != null) {
 326        // expression has already been resolved
 341830327        return;
 328      }
 1322659329      DominatingStatementLabels.PushMarker();
 330
 331      // The following cases will resolve the subexpressions and will attempt to assign a type of expr.  However, if err
 332      // and it cannot be determined what the type of expr is, then it is fine to leave expr.Type as null.  In that case
 333      // of this method will assign proxy type to the expression, which reduces the number of error messages that are pr
 334      // while type checking the rest of the program.
 335
 1464465336      if (expr is ParensExpression) {
 141806337        var e = (ParensExpression)expr;
 141806338        ResolveExpression(e.E, resolutionContext);
 141806339        var innerRange = e.E.RangeToken;
 141806340        e.ResolvedExpression = e.E; // Overwrites the range, which is not suitable for ParensExpressions
 141806341        e.E.RangeToken = innerRange;
 141806342        e.Type = e.E.Type;
 343
 1327858344      } else if (expr is ChainingExpression) {
 5199345        var e = (ChainingExpression)expr;
 5199346        ResolveExpression(e.E, resolutionContext);
 5199347        e.ResolvedExpression = e.E;
 5199348        e.Type = e.E.Type;
 349
 1210658350      } else if (expr is NegationExpression) {
 29805351        var e = (NegationExpression)expr;
 29805352        ResolveExpression(e.E, resolutionContext);
 29805353        e.Type = e.E.Type;
 29805354        AddXConstraint(e.E.tok, "NumericOrBitvector", e.E.Type, "type of unary - must be of a numeric or bitvector type 
 355        // Note, e.ResolvedExpression will be filled in during CheckTypeInference, at which time e.Type has been determi
 356
 1699341357      } else if (expr is LiteralExpr) {
 523687358        LiteralExpr e = (LiteralExpr)expr;
 359
 523687360        if (e is StaticReceiverExpr) {
 0361          StaticReceiverExpr eStatic = (StaticReceiverExpr)e;
 0362          ResolveType(eStatic.tok, eStatic.UnresolvedType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, nu
 0363          eStatic.Type = eStatic.UnresolvedType;
 523687364        } else {
 524299365          if (e.Value == null) {
 612366            e.Type = new InferredTypeProxy();
 612367            AddXConstraint(e.tok, "IsNullableRefType", e.Type, "type of 'null' is a reference type, but it is used as {0
 667531368          } else if (e.Value is BigInteger) {
 143844369            var proxy = new InferredTypeProxy();
 143844370            e.Type = proxy;
 143844371            ConstrainSubtypeRelation(new IntVarietiesSupertype(), e.Type, e.tok, "integer literal used as if it had type
 565967372          } else if (e.Value is BaseTypes.BigDec) {
 42892373            var proxy = new InferredTypeProxy();
 42892374            e.Type = proxy;
 42892375            ConstrainSubtypeRelation(new RealVarietiesSupertype(), e.Type, e.tok, "type of real literal is used as {0}",
 459349376          } else if (e.Value is bool) {
 80118377            e.Type = Type.Bool;
 435930378          } else if (e is CharLiteralExpr) {
 99591379            e.Type = Type.Char;
 412851380          } else if (e is StringLiteralExpr) {
 156630381            e.Type = Type.String();
 156630382            ResolveType(e.tok, e.Type, resolutionContext, ResolveTypeOptionEnum.DontInfer, null);
 156630383          } else {
 0384            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected literal type
 385          }
 523687386        }
 1145849387      } else if (expr is ThisExpr) {
 0388        if (!scope.AllowInstance) {
 0389          reporter.Error(MessageSource.Resolver, expr, "'this' is not allowed in a 'static' context");
 0390        }
 0391        if (currentClass is ClassDecl cd && cd.IsDefaultClass) {
 392          // there's no type
 0393        } else {
 0394          if (currentClass == null) {
 0395            Contract.Assert(reporter.HasErrors);
 0396          } else {
 0397            expr.Type = GetThisType(expr.tok, currentClass);  // do this regardless of scope.AllowInstance, for better e
 0398          }
 0399        }
 400
 622162401      } else if (expr is IdentifierExpr) {
 0402        var e = (IdentifierExpr)expr;
 0403        e.Var = scope.Find(e.Name);
 0404        if (e.Var != null) {
 0405          expr.Type = e.Var.Type;
 0406        } else {
 0407          reporter.Error(MessageSource.Resolver, expr, "Identifier does not denote a local variable, parameter, or bound
 0408        }
 409
 638247410      } else if (expr is DatatypeValue) {
 16085411        DatatypeValue dtv = (DatatypeValue)expr;
 16085412        if (!moduleInfo.TopLevels.TryGetValue(dtv.DatatypeName, out var d)) {
 0413          reporter.Error(MessageSource.Resolver, expr.tok, "Undeclared datatype: {0}", dtv.DatatypeName);
 16085414        } else if (d is AmbiguousTopLevelDecl) {
 0415          var ad = (AmbiguousTopLevelDecl)d;
 0416          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modu
 16085417        } else if (!(d is DatatypeDecl)) {
 0418          reporter.Error(MessageSource.Resolver, expr.tok, "Expected datatype: {0}", dtv.DatatypeName);
 16085419        } else {
 16085420          ResolveDatatypeValue(resolutionContext, dtv, (DatatypeDecl)d, null);
 16085421        }
 422
 669082423      } else if (expr is DisplayExpression) {
 46920424        DisplayExpression e = (DisplayExpression)expr;
 46920425        Type elementType = new InferredTypeProxy() { KeepConstraints = true };
 424590426        foreach (Expression ee in e.Elements) {
 94610427          ResolveExpression(ee, resolutionContext);
 94610428          Contract.Assert(ee.Type != null);  // follows from postcondition of ResolveExpression
 94610429          ConstrainSubtypeRelation(elementType, ee.Type, ee.tok, "All elements of display must have some common supertyp
 94610430        }
 59280431        if (expr is SetDisplayExpr) {
 12360432          var se = (SetDisplayExpr)expr;
 12360433          expr.Type = new SetType(se.Finite, elementType);
 57352434        } else if (expr is MultiSetDisplayExpr) {
 10432435          expr.Type = new MultiSetType(elementType);
 34560436        } else {
 24128437          expr.Type = new SeqType(elementType);
 24128438        }
 626326439      } else if (expr is MapDisplayExpr) {
 20249440        MapDisplayExpr e = (MapDisplayExpr)expr;
 20249441        Type domainType = new InferredTypeProxy();
 20249442        Type rangeType = new InferredTypeProxy();
 237219443        foreach (ExpressionPair p in e.Elements) {
 58824444          ResolveExpression(p.A, resolutionContext);
 58824445          Contract.Assert(p.A.Type != null);  // follows from postcondition of ResolveExpression
 58824446          ConstrainSubtypeRelation(domainType, p.A.Type, p.A.tok, "All elements of display must have some common superty
 58824447          ResolveExpression(p.B, resolutionContext);
 58824448          Contract.Assert(p.B.Type != null);  // follows from postcondition of ResolveExpression
 58824449          ConstrainSubtypeRelation(rangeType, p.B.Type, p.B.tok, "All elements of display must have some common supertyp
 58824450        }
 20249451        expr.Type = new MapType(e.Finite, domainType, rangeType);
 835826452      } else if (expr is NameSegment) {
 276669453        var e = (NameSegment)expr;
 276669454        ResolveNameSegment(e, true, null, resolutionContext, false);
 455
 276669456        if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 0457          reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.Name);
 0458          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 276669459        } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 0460          reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.Name);
 0461          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 0462        }
 463
 554967464      } else if (expr is ExprDotName) {
 16059465        var e = (ExprDotName)expr;
 16059466        ResolveDotSuffix(e, true, null, resolutionContext, false);
 16059467        if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 0468          reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.SuffixName);
 0469          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 16059470        } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 0471          reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.SuffixName);
 0472          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 0473        }
 474
 262239475      } else if (expr is ApplySuffix) {
 0476        var e = (ApplySuffix)expr;
 0477        ResolveApplySuffix(e, resolutionContext, false);
 478
 246180479      } else if (expr is MemberSelectExpr) {
 0480        var e = (MemberSelectExpr)expr;
 0481        ResolveExpression(e.Obj, resolutionContext);
 0482        Contract.Assert(e.Obj.Type != null);  // follows from postcondition of ResolveExpression
 0483        var member = ResolveMember(expr.tok, e.Obj.Type, e.MemberName, out var tentativeReceiverType);
 0484        if (member == null) {
 485          // error has already been reported by ResolveMember
 0486        } else if (member is Function) {
 0487          var fn = member as Function;
 0488          e.Member = fn;
 0489          if (fn is TwoStateFunction && !resolutionContext.IsTwoState) {
 0490            reporter.Error(MessageSource.Resolver, e.tok, "a two-state function can be used only in a two-state context"
 0491          }
 492          // build the type substitution map
 0493          e.TypeApplication_AtEnclosingClass = tentativeReceiverType.TypeArgs;
 0494          e.TypeApplication_JustMember = new List<Type>();
 495          Dictionary<TypeParameter, Type> subst;
 0496          var ctype = tentativeReceiverType as UserDefinedType;
 0497          if (ctype == null) {
 0498            subst = new Dictionary<TypeParameter, Type>();
 0499          } else {
 0500            subst = TypeParameter.SubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
 0501          }
 0502          foreach (var tp in fn.TypeArgs) {
 0503            Type prox = new InferredTypeProxy();
 0504            subst[tp] = prox;
 0505            e.TypeApplication_JustMember.Add(prox);
 0506          }
 0507          subst = BuildTypeArgumentSubstitute(subst);
 0508          e.Type = SelectAppropriateArrowTypeForFunction(fn, subst, builtIns);
 0509        } else if (member is Field) {
 0510          var field = (Field)member;
 0511          e.Member = field;
 0512          e.TypeApplication_AtEnclosingClass = tentativeReceiverType.TypeArgs;
 0513          e.TypeApplication_JustMember = new List<Type>();
 0514          if (e.Obj is StaticReceiverExpr && !field.IsStatic) {
 0515            reporter.Error(MessageSource.Resolver, expr, "a field must be selected via an object, not just a class name"
 0516          }
 0517          var ctype = tentativeReceiverType as UserDefinedType;
 0518          if (ctype == null) {
 0519            e.Type = field.Type;
 0520          } else {
 0521            Contract.Assert(ctype.ResolvedClass != null); // follows from postcondition of ResolveMember
 522            // build the type substitution map
 0523            var subst = TypeParameter.SubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
 0524            e.Type = field.Type.Subst(subst);
 0525          }
 0526        } else {
 0527          reporter.Error(MessageSource.Resolver, expr, "member {0} in type {1} does not refer to a field or a function",
 0528        }
 529
 278014530      } else if (expr is SeqSelectExpr) {
 31834531        SeqSelectExpr e = (SeqSelectExpr)expr;
 31834532        ResolveSeqSelectExpr(e, resolutionContext);
 533
 246180534      } else if (expr is MultiSelectExpr) {
 0535        MultiSelectExpr e = (MultiSelectExpr)expr;
 536
 0537        ResolveExpression(e.Array, resolutionContext);
 0538        Contract.Assert(e.Array.Type != null);  // follows from postcondition of ResolveExpression
 0539        Contract.Assert(e.Array.Type.TypeArgs != null);  // if it is null, should make a 1-element list with a Proxy
 0540        Type elementType = e.Array.Type.TypeArgs.Count > 0 ?
 0541          e.Array.Type.TypeArgs[0] :
 0542          new InferredTypeProxy();
 0543        ConstrainSubtypeRelation(ResolvedArrayType(e.Array.tok, e.Indices.Count, elementType, resolutionContext, true), 
 0544          "array selection requires an array{0} (got {1})", e.Indices.Count, e.Array.Type);
 0545        int i = 0;
 0546        foreach (Expression idx in e.Indices) {
 0547          Contract.Assert(idx != null);
 0548          ResolveExpression(idx, resolutionContext);
 0549          Contract.Assert(idx.Type != null);  // follows from postcondition of ResolveExpression
 0550          ConstrainToIntegerType(idx, true, "array selection requires integer- or bitvector-based numeric indices (got {
 0551          i++;
 0552        }
 0553        e.Type = elementType;
 554
 217841555      } else if (expr is SeqUpdateExpr) {
 3495556        SeqUpdateExpr e = (SeqUpdateExpr)expr;
 3495557        ResolveExpression(e.Seq, resolutionContext);
 3495558        Contract.Assert(e.Seq.Type != null);  // follows from postcondition of ResolveExpression
 3495559        ResolveExpression(e.Index, resolutionContext);
 3495560        ResolveExpression(e.Value, resolutionContext);
 3495561        AddXConstraint(expr.tok, "SeqUpdatable", e.Seq.Type, e.Index, e.Value, "update requires a sequence, map, or mult
 3495562        expr.Type = new InferredTypeProxy(); // drop type constraints
 3495563        ConstrainSubtypeRelation(
 3495564          super: expr.Type, sub: e.Seq.Type, // expr.Type generalizes e.Seq.Type by dropping constraints
 3495565          exprForToken: expr,
 3495566          msg: "Update expression used with type '{0}'", e.Seq.Type);
 214346567      } else if (expr is DatatypeUpdateExpr) {
 0568        var e = (DatatypeUpdateExpr)expr;
 0569        ResolveExpression(e.Root, resolutionContext);
 0570        var ty = PartiallyResolveTypeForMemberSelection(expr.tok, e.Root.Type);
 0571        if (!ty.IsDatatype) {
 0572          reporter.Error(MessageSource.Resolver, expr, "datatype update expression requires a root expression of a datat
 0573        } else {
 0574          var (ghostLet, compiledLet) = ResolveDatatypeUpdate(expr.tok, e.Root, ty.AsDatatype, e.Updates, resolutionCont
 0575            out var members, out var legalSourceConstructors);
 0576          Contract.Assert((ghostLet == null) == (compiledLet == null));
 0577          if (ghostLet != null) {
 0578            e.ResolvedExpression = ghostLet; // this might be replaced by e.ResolvedCompiledExpression in CheckIsCompila
 0579            e.ResolvedCompiledExpression = compiledLet;
 0580            e.Members = members;
 0581            e.LegalSourceConstructors = legalSourceConstructors;
 0582            expr.Type = ghostLet.Type;
 0583          }
 0584        }
 585
 210851586      } else if (expr is FunctionCallExpr) {
 0587        var e = (FunctionCallExpr)expr;
 0588        ResolveFunctionCallExpr(e, resolutionContext);
 589
 210851590      } else if (expr is ApplyExpr) {
 0591        var e = (ApplyExpr)expr;
 0592        ResolveExpression(e.Function, resolutionContext);
 0593        foreach (var arg in e.Args) {
 0594          ResolveExpression(arg, resolutionContext);
 0595        }
 596
 597        // TODO: the following should be replaced by a type-class constraint that constrains the types of e.Function, e.
 0598        var fnType = e.Function.Type.AsArrowType;
 0599        if (fnType == null) {
 0600          reporter.Error(MessageSource.Resolver, e.tok,
 0601            "non-function expression (of type {0}) is called with parameters", e.Function.Type);
 0602        } else if (fnType.Arity != e.Args.Count) {
 0603          reporter.Error(MessageSource.Resolver, e.tok,
 0604            "wrong number of arguments to function application (function type '{0}' expects {1}, got {2})", fnType,
 0605            fnType.Arity, e.Args.Count);
 0606        } else {
 0607          for (var i = 0; i < fnType.Arity; i++) {
 0608            AddAssignableConstraint(e.Args[i].tok, fnType.Args[i], e.Args[i].Type,
 0609              "type mismatch for argument" + (fnType.Arity == 1 ? "" : " " + i) + " (function expects {0}, got {1})");
 0610          }
 0611        }
 612
 0613        expr.Type = fnType == null ? new InferredTypeProxy() : fnType.Result;
 614
 210851615      } else if (expr is SeqConstructionExpr) {
 0616        var e = (SeqConstructionExpr)expr;
 0617        var elementType = e.ExplicitElementType ?? new InferredTypeProxy();
 0618        ResolveType(e.tok, elementType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0619        ResolveExpression(e.N, resolutionContext);
 0620        ConstrainToIntegerType(e.N, false, "sequence construction must use an integer-based expression for the sequence 
 0621        ResolveExpression(e.Initializer, resolutionContext);
 0622        var arrowType = new ArrowType(e.tok, builtIns.ArrowTypeDecls[1], new List<Type>() { builtIns.Nat() }, elementTyp
 0623        var hintString = " (perhaps write '_ =>' in front of the expression you gave in order to make it an arrow type)"
 0624        ConstrainSubtypeRelation(arrowType, e.Initializer.Type, e.Initializer, "sequence-construction initializer expres
 0625          arrowType, e.Initializer.Type, new LazyString_OnTypeEquals(elementType, e.Initializer.Type, hintString));
 0626        expr.Type = new SeqType(elementType);
 627
 213743628      } else if (expr is MultiSetFormingExpr) {
 2892629        MultiSetFormingExpr e = (MultiSetFormingExpr)expr;
 2892630        ResolveExpression(e.E, resolutionContext);
 2892631        var elementType = new InferredTypeProxy();
 2892632        AddXConstraint(e.E.tok, "MultiSetConvertible", e.E.Type, elementType, "can only form a multiset from a seq or se
 2892633        expr.Type = new MultiSetType(elementType);
 634
 210851635      } else if (expr is OldExpr) {
 0636        var e = (OldExpr)expr;
 0637        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "old", resolutionContext);
 0638        ResolveExpression(e.E, new ResolutionContext(resolutionContext.CodeContext, false) with { InOld = true });
 0639        expr.Type = e.E.Type;
 640
 207959641      } else if (expr is UnchangedExpr) {
 0642        var e = (UnchangedExpr)expr;
 0643        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "unchanged", resolutionContext);
 0644        foreach (var fe in e.Frame) {
 0645          ResolveFrameExpression(fe, FrameExpressionUse.Unchanged, resolutionContext);
 0646        }
 0647        expr.Type = Type.Bool;
 648
 207959649      } else if (expr is FreshExpr) {
 0650        var e = (FreshExpr)expr;
 0651        ResolveExpression(e.E, resolutionContext);
 0652        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "fresh", resolutionContext);
 653        // the type of e.E must be either an object or a set/seq of objects
 0654        AddXConstraint(expr.tok, "Freshable", e.E.Type, "the argument of a fresh expression must denote an object or a s
 0655        expr.Type = Type.Bool;
 656
 229053657      } else if (expr is UnaryOpExpr) {
 21094658        var e = (UnaryOpExpr)expr;
 21094659        ResolveExpression(e.E, resolutionContext);
 21094660        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 21094661        switch (e.Op) {
 662          case UnaryOpExpr.Opcode.Not:
 212663            AddXConstraint(e.E.tok, "BooleanBits", e.E.Type, "logical/bitwise negation expects a boolean or bitvector ar
 212664            expr.Type = e.E.Type;
 212665            break;
 666          case UnaryOpExpr.Opcode.Cardinality:
 20882667            AddXConstraint(expr.tok, "Sizeable", e.E.Type, "size operator expects a collection argument (instead got {0}
 20882668            expr.Type = Type.Int;
 20882669            break;
 670          case UnaryOpExpr.Opcode.Allocated:
 671            // the argument is allowed to have any type at all
 0672            expr.Type = Type.Bool;
 0673            if (2 <= Options.Allocated &&
 0674              ((resolutionContext.CodeContext is Function && !resolutionContext.InOld) || resolutionContext.CodeContext 
 0675              var declKind = CodeContextWrapper.Unwrap(resolutionContext.CodeContext) is RedirectingTypeDecl redir ? red
 0676              reporter.Error(MessageSource.Resolver, expr, "a {0} definition is not allowed to depend on the set of allo
 0677            }
 0678            break;
 679          default:
 0680            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected unary operator
 681        }
 682
 683        // We do not have enough information to compute `e.ResolvedOp` yet.
 684        // For binary operators the computation happens in `CheckTypeInference`.
 685        // For unary operators it happens lazily in the getter of `e.ResolvedOp`.
 207959686      } else if (expr is ConversionExpr) {
 0687        var e = (ConversionExpr)expr;
 0688        ResolveExpression(e.E, resolutionContext);
 0689        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 0690        ResolveType(e.tok, e.ToType, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies), n
 0691        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 0692          if (e.ToType.IsNumericBased(Type.NumericPersuasion.Int)) {
 0693            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to an int-based typ
 0694          } else if (e.ToType.IsNumericBased(Type.NumericPersuasion.Real)) {
 0695            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a real-based typ
 0696          } else if (e.ToType.IsBitVectorType) {
 0697            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a bitvector-base
 0698          } else if (e.ToType.IsCharType) {
 0699            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a char type is a
 0700          } else if (e.ToType.IsBigOrdinalType) {
 0701            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to an ORDINAL type 
 0702          } else if (e.ToType.IsRefType) {
 0703            AddAssignableConstraint(expr.tok, e.ToType, e.E.Type, "type cast to reference type '{0}' must be from an exp
 0704          } else {
 0705            reporter.Error(MessageSource.Resolver, expr, "type conversions are not supported to this type (got {0})", e.
 0706          }
 0707          e.Type = e.ToType;
 0708        } else {
 0709          e.Type = new InferredTypeProxy();
 0710        }
 711
 186865712      } else if (expr is TypeTestExpr) {
 0713        var e = (TypeTestExpr)expr;
 0714        ResolveExpression(e.E, resolutionContext);
 0715        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 0716        ResolveType(e.tok, e.ToType, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies), n
 0717        AddAssignableConstraint(expr.tok, e.ToType, e.E.Type, "type test for type '{0}' must be from an expression assig
 0718        e.Type = Type.Bool;
 719
 336829720      } else if (expr is BinaryExpr) {
 721
 149964722        BinaryExpr e = (BinaryExpr)expr;
 149964723        ResolveExpression(e.E0, resolutionContext);
 149964724        Contract.Assert(e.E0.Type != null);  // follows from postcondition of ResolveExpression
 149964725        ResolveExpression(e.E1, resolutionContext);
 149964726        Contract.Assert(e.E1.Type != null);  // follows from postcondition of ResolveExpression
 727
 149964728        switch (e.Op) {
 729          case BinaryExpr.Opcode.Iff:
 730          case BinaryExpr.Opcode.Imp:
 731          case BinaryExpr.Opcode.Exp:
 732          case BinaryExpr.Opcode.And:
 42567733          case BinaryExpr.Opcode.Or: {
 42567734              ConstrainSubtypeRelation(Type.Bool, e.E0.Type, expr, "first argument to {0} must be of type bool (instead 
 42567735              var secondArgumentDescription = e.E1.tok is QuantifiedVariableRangeToken
 42567736                ? "range of quantified variable" : "second argument to {0}";
 42567737              ConstrainSubtypeRelation(Type.Bool, e.E1.Type, expr, secondArgumentDescription + " must be of type bool (i
 42567738              expr.Type = Type.Bool;
 42567739              break;
 740            }
 741
 742          case BinaryExpr.Opcode.Eq:
 743          case BinaryExpr.Opcode.Neq:
 52248744            AddXConstraint(expr.tok, "Equatable", e.E0.Type, e.E1.Type, "arguments must have comparable types (got {0} a
 52248745            expr.Type = Type.Bool;
 52248746            break;
 747
 748          case BinaryExpr.Opcode.Disjoint:
 182749            Type disjointArgumentsType = new InferredTypeProxy();
 182750            ConstrainSubtypeRelation(disjointArgumentsType, e.E0.Type, expr, "arguments to {2} must have a common supert
 182751            ConstrainSubtypeRelation(disjointArgumentsType, e.E1.Type, expr, "arguments to {2} must have a common supert
 182752            AddXConstraint(expr.tok, "Disjointable", disjointArgumentsType, "arguments must be of a set or multiset type
 182753            expr.Type = Type.Bool;
 182754            break;
 755
 756          case BinaryExpr.Opcode.Lt:
 17465757          case BinaryExpr.Opcode.Le: {
 17465758              if (e.Op == BinaryExpr.Opcode.Lt && (PartiallyResolveTypeForMemberSelection(e.E0.tok, e.E0.Type).IsIndData
 0759                AddXConstraint(expr.tok, "RankOrderable", e.E0.Type, e.E1.Type, "arguments to rank comparison must be da
 0760                e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankLt;
 17465761              } else {
 17465762                var cmpType = new InferredTypeProxy();
 17465763                var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, "arguments to {2} must have a common supertype 
 17465764                ConstrainSubtypeRelation(cmpType, e.E0.Type, err);
 17465765                ConstrainSubtypeRelation(cmpType, e.E1.Type, err);
 17465766                AddXConstraint(expr.tok, "Orderable_Lt", e.E0.Type, e.E1.Type,
 17465767                  "arguments to " + BinaryExpr.OpcodeString(e.Op) + " must be of a numeric type, bitvector type, ORDINAL
 17465768              }
 17465769              expr.Type = Type.Bool;
 17465770            }
 17465771            break;
 772
 773          case BinaryExpr.Opcode.Gt:
 19802774          case BinaryExpr.Opcode.Ge: {
 19802775              if (e.Op == BinaryExpr.Opcode.Gt && (PartiallyResolveTypeForMemberSelection(e.E0.tok, e.E0.Type).IsIndData
 0776                AddXConstraint(expr.tok, "RankOrderable", e.E1.Type, e.E0.Type, "arguments to rank comparison must be da
 0777                e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankGt;
 19802778              } else {
 19802779                var cmpType = new InferredTypeProxy();
 19802780                var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, "arguments to {2} must have a common supertype 
 19802781                ConstrainSubtypeRelation(cmpType, e.E0.Type, err);
 19802782                ConstrainSubtypeRelation(cmpType, e.E1.Type, err);
 19802783                AddXConstraint(expr.tok, "Orderable_Gt", e.E0.Type, e.E1.Type,
 19802784                  "arguments to " + BinaryExpr.OpcodeString(e.Op) + " must be of a numeric type, bitvector type, ORDINAL
 19802785              }
 19802786              expr.Type = Type.Bool;
 19802787            }
 19802788            break;
 789
 790          case BinaryExpr.Opcode.LeftShift:
 0791          case BinaryExpr.Opcode.RightShift: {
 0792              expr.Type = new InferredTypeProxy();
 0793              AddXConstraint(e.tok, "IsBitvector", expr.Type, "type of " + BinaryExpr.OpcodeString(e.Op) + " must be a b
 0794              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to " + BinaryExpr.OpcodeSt
 0795              AddXConstraint(expr.tok, "IntLikeOrBitvector", e.E1.Type, "type of right argument to " + BinaryExpr.Opcode
 0796            }
 0797            break;
 798
 3031799          case BinaryExpr.Opcode.Add: {
 3031800              expr.Type = new InferredTypeProxy();
 3031801              AddXConstraint(e.tok, "Plussable", expr.Type, "type of + must be of a numeric type, a bitvector type, ORDI
 3031802              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to + ({0}) must agree with
 3031803              ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to + ({0}) must agree wit
 3031804            }
 3031805            break;
 806
 2586807          case BinaryExpr.Opcode.Sub: {
 2586808              expr.Type = new InferredTypeProxy();
 2586809              AddXConstraint(e.tok, "Minusable", expr.Type, "type of - must be of a numeric type, bitvector type, ORDINA
 2586810              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to - ({0}) must agree with
 811              // The following handles map subtraction, but does not in an unfortunately restrictive way.
 812              // First, it would be nice to delay the decision of it this is a map subtraction or not. This settles
 813              // for the simple way to decide based on what is currently known about the result type, which is also
 814              // done, for example, when deciding if "<" denotes rank ordering on datatypes.
 815              // Second, for map subtraction, it would be nice to allow the right-hand operand to be either a set or
 816              // an iset. That would also lead to further complexity in the code, so this code restricts the right-hand
 817              // operand to be a set.
 2586818              var eType = PartiallyResolveTypeForMemberSelection(expr.tok, expr.Type).AsMapType;
 3057819              if (eType != null) {
 820                // allow "map - set == map"
 471821                var expected = new SetType(true, eType.Domain);
 471822                ConstrainSubtypeRelation(expected, e.E1.Type, expr.tok, "map subtraction expects right-hand operand to h
 2586823              } else {
 2115824                ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to - ({0}) must agree w
 2115825              }
 2586826            }
 2586827            break;
 828
 683829          case BinaryExpr.Opcode.Mul: {
 683830              expr.Type = new InferredTypeProxy();
 683831              AddXConstraint(e.tok, "Mullable", expr.Type, "type of * must be of a numeric type, bitvector type, or a se
 683832              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to * ({0}) must agree with
 683833              ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to * ({0}) must agree wit
 683834            }
 683835            break;
 836
 837          case BinaryExpr.Opcode.In:
 838          case BinaryExpr.Opcode.NotIn:
 8313839            var subjectDescription = e.E1.tok is QuantifiedVariableDomainToken
 8313840              ? "domain of quantified variable" : "second argument to \"" + BinaryExpr.OpcodeString(e.Op) + "\"";
 8313841            AddXConstraint(expr.tok, "Innable", e.E1.Type, e.E0.Type, subjectDescription + " must be a set, multiset, or
 8313842            expr.Type = Type.Bool;
 8313843            break;
 844
 845          case BinaryExpr.Opcode.Div:
 1607846            expr.Type = new InferredTypeProxy();
 1607847            AddXConstraint(expr.tok, "NumericOrBitvector", expr.Type, "arguments to " + BinaryExpr.OpcodeString(e.Op) + 
 1607848            ConstrainSubtypeRelation(expr.Type, e.E0.Type,
 1607849              expr, "type of left argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result typ
 1607850              e.E0.Type, expr.Type);
 1607851            ConstrainSubtypeRelation(expr.Type, e.E1.Type,
 1607852              expr, "type of right argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result ty
 1607853              e.E1.Type, expr.Type);
 1607854            break;
 855
 856          case BinaryExpr.Opcode.Mod:
 1480857            expr.Type = new InferredTypeProxy();
 1480858            AddXConstraint(expr.tok, "IntLikeOrBitvector", expr.Type, "arguments to " + BinaryExpr.OpcodeString(e.Op) + 
 1480859            ConstrainSubtypeRelation(expr.Type, e.E0.Type,
 1480860              expr, "type of left argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result typ
 1480861              e.E0.Type, expr.Type);
 1480862            ConstrainSubtypeRelation(expr.Type, e.E1.Type,
 1480863              expr, "type of right argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result ty
 1480864              e.E1.Type, expr.Type);
 1480865            break;
 866
 867          case BinaryExpr.Opcode.BitwiseAnd:
 868          case BinaryExpr.Opcode.BitwiseOr:
 869          case BinaryExpr.Opcode.BitwiseXor:
 0870            expr.Type = NewIntegerBasedProxy(expr.tok);
 0871            var errFormat = "first argument to " + BinaryExpr.OpcodeString(e.Op) + " must be of a bitvector type (instea
 0872            ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr, errFormat, e.E0.Type);
 0873            AddXConstraint(expr.tok, "IsBitvector", e.E0.Type, errFormat);
 0874            errFormat = "second argument to " + BinaryExpr.OpcodeString(e.Op) + " must be of a bitvector type (instead g
 0875            ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr, errFormat, e.E1.Type);
 0876            AddXConstraint(expr.tok, "IsBitvector", e.E1.Type, errFormat);
 0877            break;
 878
 879          default:
 0880            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected operator
 881        }
 882        // We should also fill in e.ResolvedOp, but we may not have enough information for that yet.  So, instead, delay
 883        // setting e.ResolvedOp until inside CheckTypeInference.
 884
 186865885      } else if (expr is TernaryExpr) {
 0886        var e = (TernaryExpr)expr;
 0887        ResolveExpression(e.E0, resolutionContext);
 0888        ResolveExpression(e.E1, resolutionContext);
 0889        ResolveExpression(e.E2, resolutionContext);
 0890        switch (e.Op) {
 891          case TernaryExpr.Opcode.PrefixEqOp:
 892          case TernaryExpr.Opcode.PrefixNeqOp:
 0893            AddXConstraint(expr.tok, "IntOrORDINAL", e.E0.Type, "prefix-equality limit argument must be an ORDINAL or in
 0894            AddXConstraint(expr.tok, "Equatable", e.E1.Type, e.E2.Type, "arguments must have the same type (got {0} and 
 0895            AddXConstraint(expr.tok, "IsCoDatatype", e.E1.Type, "arguments to prefix equality must be codatatypes (inste
 0896            expr.Type = Type.Bool;
 0897            break;
 898          default:
 0899            Contract.Assert(false);  // unexpected ternary operator
 0900            break;
 901        }
 902
 36901903      } else if (expr is LetExpr) {
 0904        var e = (LetExpr)expr;
 0905        if (e.Exact) {
 0906          foreach (var rhs in e.RHSs) {
 0907            ResolveExpression(rhs, resolutionContext);
 0908          }
 0909          scope.PushMarker();
 0910          if (e.LHSs.Count != e.RHSs.Count) {
 0911            reporter.Error(MessageSource.Resolver, expr, "let expression must have same number of LHSs (found {0}) as RH
 0912          }
 0913          var i = 0;
 0914          foreach (var lhs in e.LHSs) {
 0915            var rhsType = i < e.RHSs.Count ? e.RHSs[i].Type : new InferredTypeProxy();
 0916            ResolveCasePattern(lhs, rhsType, resolutionContext);
 917            // Check for duplicate names now, because not until after resolving the case pattern do we know if identifie
 0918            var c = 0;
 0919            foreach (var v in lhs.Vars) {
 0920              ScopePushAndReport(scope, v, "let-variable");
 0921              c++;
 0922            }
 0923            if (c == 0) {
 924              // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constan
 0925              reporter.Error(MessageSource.Resolver, lhs.tok, "LHS is a constant literal; to be legal, it must introduce
 0926            }
 0927            i++;
 0928          }
 0929        } else {
 930          // let-such-that expression
 0931          if (e.RHSs.Count != 1) {
 0932            reporter.Error(MessageSource.Resolver, expr, "let-such-that expression must have just one RHS (found {0})", 
 0933          }
 934          // the bound variables are in scope in the RHS of a let-such-that expression
 0935          scope.PushMarker();
 0936          foreach (var lhs in e.LHSs) {
 0937            Contract.Assert(lhs.Var != null);  // the parser already checked that every LHS is a BoundVar, not a general
 0938            var v = lhs.Var;
 0939            ScopePushAndReport(scope, v, "let-variable");
 0940            ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0941          }
 0942          foreach (var rhs in e.RHSs) {
 0943            ResolveExpression(rhs, resolutionContext);
 0944            ConstrainTypeExprBool(rhs, "type of RHS of let-such-that expression must be boolean (got {0})");
 0945          }
 0946        }
 0947        ResolveExpression(e.Body, resolutionContext);
 0948        ResolveAttributes(e, resolutionContext);
 0949        scope.PopMarker();
 0950        expr.Type = e.Body.Type;
 36901951      } else if (expr is LetOrFailExpr) {
 0952        var e = (LetOrFailExpr)expr;
 0953        ResolveLetOrFailExpr(e, resolutionContext);
 36901954      } else if (expr is QuantifierExpr) {
 0955        var e = (QuantifierExpr)expr;
 0956        Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 0957        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 0958        scope.PushMarker();
 0959        foreach (BoundVar v in e.BoundVars) {
 0960          ScopePushAndReport(scope, v, "bound-variable");
 0961          var option = new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies);
 0962          ResolveType(v.tok, v.Type, resolutionContext, option, null);
 0963        }
 0964        if (e.Range != null) {
 0965          ResolveExpression(e.Range, resolutionContext);
 0966          Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 0967          ConstrainTypeExprBool(e.Range, "range of quantifier must be of type bool (instead got {0})");
 0968        }
 0969        ResolveExpression(e.Term, resolutionContext);
 0970        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 0971        ConstrainTypeExprBool(e.Term, "body of quantifier must be of type bool (instead got {0})");
 972        // Since the body is more likely to infer the types of the bound variables, resolve it
 973        // first (above) and only then resolve the attributes (below).
 0974        ResolveAttributes(e, resolutionContext);
 0975        scope.PopMarker();
 0976        expr.Type = Type.Bool;
 977
 36901978      } else if (expr is SetComprehension) {
 0979        var e = (SetComprehension)expr;
 0980        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 0981        scope.PushMarker();
 0982        foreach (BoundVar v in e.BoundVars) {
 0983          ScopePushAndReport(scope, v, "bound-variable");
 0984          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0985          var inferredProxy = v.Type as InferredTypeProxy;
 0986          if (inferredProxy != null) {
 0987            Contract.Assert(!inferredProxy.KeepConstraints);  // in general, this proxy is inferred to be a base type
 0988          }
 0989        }
 0990        ResolveExpression(e.Range, resolutionContext);
 0991        Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 0992        ConstrainTypeExprBool(e.Range, "range of comprehension must be of type bool (instead got {0})");
 0993        ResolveExpression(e.Term, resolutionContext);
 0994        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 995
 0996        ResolveAttributes(e, resolutionContext);
 0997        scope.PopMarker();
 0998        expr.Type = new SetType(e.Finite, e.Term.Type);
 999
 369011000      } else if (expr is MapComprehension) {
 01001        var e = (MapComprehension)expr;
 01002        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 01003        scope.PushMarker();
 01004        Contract.Assert(e.BoundVars.Count == 1 || (1 < e.BoundVars.Count && e.TermLeft != null));
 01005        foreach (BoundVar v in e.BoundVars) {
 01006          ScopePushAndReport(scope, v, "bound-variable");
 01007          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 01008          var inferredProxy = v.Type as InferredTypeProxy;
 01009          if (inferredProxy != null) {
 01010            Contract.Assert(!inferredProxy.KeepConstraints);  // in general, this proxy is inferred to be a base type
 01011          }
 01012        }
 01013        ResolveExpression(e.Range, resolutionContext);
 01014        Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 01015        ConstrainTypeExprBool(e.Range, "range of comprehension must be of type bool (instead got {0})");
 01016        if (e.TermLeft != null) {
 01017          ResolveExpression(e.TermLeft, resolutionContext);
 01018          Contract.Assert(e.TermLeft.Type != null);  // follows from postcondition of ResolveExpression
 01019        }
 01020        ResolveExpression(e.Term, resolutionContext);
 01021        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 1022
 01023        ResolveAttributes(e, resolutionContext);
 01024        scope.PopMarker();
 01025        expr.Type = new MapType(e.Finite, e.TermLeft != null ? e.TermLeft.Type : e.BoundVars[0].Type, e.Term.Type);
 1026
 369011027      } else if (expr is LambdaExpr) {
 01028        var e = (LambdaExpr)expr;
 01029        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 01030        scope.PushMarker();
 01031        foreach (BoundVar v in e.BoundVars) {
 01032          ScopePushAndReport(scope, v, "bound-variable");
 01033          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 01034        }
 1035
 01036        if (e.Range != null) {
 01037          ResolveExpression(e.Range, resolutionContext);
 01038          Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 01039          ConstrainTypeExprBool(e.Range, "Precondition must be boolean (got {0})");
 01040        }
 01041        foreach (var read in e.Reads) {
 01042          ResolveFrameExpression(read, FrameExpressionUse.Reads, resolutionContext);
 01043        }
 01044        ResolveExpression(e.Term, resolutionContext);
 01045        Contract.Assert(e.Term.Type != null);
 01046        scope.PopMarker();
 01047        expr.Type = SelectAppropriateArrowType(e.tok, e.BoundVars.ConvertAll(v => v.Type), e.Body.Type, e.Reads.Count !=
 369011048      } else if (expr is WildcardExpr) {
 01049        expr.Type = new SetType(true, builtIns.ObjectQ());
 369011050      } else if (expr is StmtExpr) {
 01051        var e = (StmtExpr)expr;
 01052        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 1053
 01054        ResolveStatement(e.S, resolutionContext);
 01055        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 01056          var r = e.S as UpdateStmt;
 01057          if (r != null && r.ResolvedStatements.Count == 1) {
 01058            var call = r.ResolvedStatements[0] as CallStmt;
 01059            if (call.Method is TwoStateLemma && !resolutionContext.IsTwoState) {
 01060              reporter.Error(MessageSource.Resolver, call, "two-state lemmas can only be used in two-state contexts");
 01061            }
 01062          }
 01063        }
 1064
 01065        ResolveExpression(e.E, resolutionContext);
 01066        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 01067        expr.Type = e.E.Type;
 1068
 674091069      } else if (expr is ITEExpr) {
 305081070        ITEExpr e = (ITEExpr)expr;
 305081071        ResolveExpression(e.Test, resolutionContext);
 305081072        Contract.Assert(e.Test.Type != null);  // follows from postcondition of ResolveExpression
 305081073        ResolveExpression(e.Thn, resolutionContext);
 305081074        Contract.Assert(e.Thn.Type != null);  // follows from postcondition of ResolveExpression
 305081075        ResolveExpression(e.Els, resolutionContext);
 305081076        Contract.Assert(e.Els.Type != null);  // follows from postcondition of ResolveExpression
 305081077        ConstrainTypeExprBool(e.Test, "guard condition in if-then-else expression must be a boolean (instead got {0})");
 305081078        expr.Type = new InferredTypeProxy();
 305081079        ConstrainSubtypeRelation(expr.Type, e.Thn.Type, expr, "the two branches of an if-then-else expression must have 
 305081080        ConstrainSubtypeRelation(expr.Type, e.Els.Type, expr, "the two branches of an if-then-else expression must have 
 1081
 432941082      } else if (expr is NestedMatchExpr nestedMatchExpr) {
 63931083        ResolveNestedMatchExpr(nestedMatchExpr, resolutionContext);
 63931084      } else {
 01085        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected expression
 1086      }
 1087
 13226591088      if (expr.Type == null) {
 1089        // some resolution error occurred
 01090        expr.Type = new InferredTypeProxy();
 01091      }
 1092
 13226591093      DominatingStatementLabels.PopMarker();
 16644891094    }
 1095
 179581096    void ResolveTypeParameters(List<TypeParameter/*!*/>/*!*/ tparams, bool emitErrors, TypeParameter.ParentType/*!*/ par
 1097      Contract.Requires(tparams != null);
 1098      Contract.Requires(parent != null);
 1099      // push non-duplicated type parameter names
 179581100      int index = 0;
 700561101      foreach (TypeParameter tp in tparams) {
 79381102        if (emitErrors) {
 1103          // we're seeing this TypeParameter for the first time
 25441104          tp.Parent = parent;
 25441105          tp.PositionalIndex = index;
 25441106        }
 53941107        var r = allTypeParameters.Push(tp.Name, tp);
 79381108        if (emitErrors) {
 25441109          if (r == Scope<TypeParameter>.PushResult.Duplicate) {
 01110            reporter.Error(MessageSource.Resolver, ErrorRegistry.NoneId, tp, "Duplicate type-parameter name: {0}", tp.Na
 25441111          } else if (r == Scope<TypeParameter>.PushResult.Shadow) {
 01112            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, tp.tok, "Shadowed type-parameter name: {0}", 
 01113          }
 25441114        }
 53941115      }
 179581116    }
 1117
 2108461118    private bool ConstrainSubtypeRelation(Type super, Type sub, Expression exprForToken, string msg, params object[] msg
 1119      Contract.Requires(sub != null);
 1120      Contract.Requires(super != null);
 1121      Contract.Requires(exprForToken != null);
 1122      Contract.Requires(msg != null);
 1123      Contract.Requires(msgArgs != null);
 2108461124      return ConstrainSubtypeRelation(super, sub, exprForToken.tok, msg, msgArgs);
 2108461125    }
 1126
 429761127    public void ConstrainTypeExprBool(Expression e, string msg) {
 1128      Contract.Requires(e != null);
 1129      Contract.Requires(msg != null);  // expected to have a {0} part
 429761130      ConstrainSubtypeRelation(Type.Bool, e.Type, e, msg, e.Type);
 429761131    }
 1132
 6406091133    public bool ConstrainSubtypeRelation(Type super, Type sub, IToken tok, string msg, params object[] msgArgs) {
 1134      Contract.Requires(sub != null);
 1135      Contract.Requires(super != null);
 1136      Contract.Requires(tok != null);
 1137      Contract.Requires(msg != null);
 1138      Contract.Requires(msgArgs != null);
 6406091139      return ConstrainSubtypeRelation(super, sub, new TypeConstraint.ErrorMsgWithToken(tok, msg, msgArgs));
 6406091140    }
 1141
 2272701142    private void ConstrainAssignable(NonProxyType lhs, Type rhs, TypeConstraint.ErrorMsg errMsg, out bool moreXConstrain
 1143      Contract.Requires(lhs != null);
 1144      Contract.Requires(rhs != null);
 1145      Contract.Requires(errMsg != null);
 1146
 2272701147      DetermineRootLeaf(lhs, out var isRoot, out _, out _, out _);
 4422781148      if (isRoot) {
 2150081149        ConstrainSubtypeRelation(lhs, rhs, errMsg, true, allowDecisions);
 2150081150        moreXConstraints = false;
 2272701151      } else {
 122621152        var lhsWithProxyArgs = Type.HeadWithProxyArgs(lhs);
 122621153        ConstrainSubtypeRelation(lhsWithProxyArgs, rhs, errMsg, false, allowDecisions);
 122621154        ConstrainAssignableTypeArgs(lhs, lhsWithProxyArgs.TypeArgs, lhs.TypeArgs, errMsg, out moreXConstraints);
 234131155        if (lhs.AsCollectionType == null) {
 111511156          var sameHead = Type.SameHead(lhs, rhs);
 111511157          if (!sameHead && lhs is UserDefinedType udtLhs && rhs is UserDefinedType udtRhs) {
 1158            // also allow the case where lhs is a possibly-null type and rhs is a non-null type
 01159            sameHead = udtLhs.ResolvedClass == (udtRhs.ResolvedClass as NonNullTypeDecl)?.Class;
 01160          }
 216691161          if (sameHead) {
 105181162            ConstrainAssignableTypeArgs(lhs, lhs.TypeArgs, rhs.TypeArgs, errMsg, out var more2);
 105181163            moreXConstraints = moreXConstraints || more2;
 105181164          }
 111511165        }
 122621166      }
 2272701167    }
 1168
 369301169    private void ConstrainAssignableTypeArgs(Type typeHead, List<Type> A, List<Type> B, TypeConstraint.ErrorMsg errMsg, 
 1170      Contract.Requires(typeHead != null);
 1171      Contract.Requires(A != null);
 1172      Contract.Requires(B != null);
 1173      Contract.Requires(A.Count == B.Count);
 1174      Contract.Requires(errMsg != null);
 1175
 369301176      var tok = errMsg.Tok;
 415931177      if (B.Count == 0) {
 1178        // all done
 46631179        moreXConstraints = false;
 388231180      } else if (typeHead is MapType) {
 18931181        var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter at index 0 expects {1} <: {0
 18931182        AddAssignableConstraint(tok, A[0], B[0], em);
 18931183        em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter at index 1 expects {1} <: {0}", 
 18931184        AddAssignableConstraint(tok, A[1], B[1], em);
 18931185        moreXConstraints = true;
 409321186      } else if (typeHead is CollectionType) {
 86651187        var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter expects {1} <: {0}", A[0], B
 86651188        AddAssignableConstraint(tok, A[0], B[0], em);
 86651189        moreXConstraints = true;
 303741190      } else {
 217091191        var udt = (UserDefinedType)typeHead;  // note, collections, maps, and user-defined types are the only one with T
 217091192        var cl = udt.ResolvedClass;
 217091193        Contract.Assert(cl != null);
 217091194        Contract.Assert(cl.TypeArgs.Count == B.Count);
 217091195        moreXConstraints = false;
 1134051196        for (int i = 0; i < B.Count; i++) {
 233291197          var msgFormat = "variance for type parameter" + (B.Count == 1 ? "" : " at index " + i) + " expects {0} {1} {2}
 260491198          if (cl.TypeArgs[i].Variance == TypeParameter.TPVariance.Co) {
 27201199            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "co" + msgFormat, A[i], ":>", B[i]);
 27201200            AddAssignableConstraint(tok, A[i], B[i], em);
 27201201            moreXConstraints = true;
 233291202          } else if (cl.TypeArgs[i].Variance == TypeParameter.TPVariance.Contra) {
 01203            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "contra" + msgFormat, A[i], "<:", B[i]);
 01204            AddAssignableConstraint(tok, B[i], A[i], em);
 01205            moreXConstraints = true;
 206091206          } else {
 206091207            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "non" + msgFormat, A[i], "=", B[i]);
 206091208            ConstrainSubtypeRelation_Equal(A[i], B[i], em);
 206091209          }
 233291210        }
 217091211      }
 369301212    }
 1213
 1214    /// <summary>
 1215    /// Adds the subtyping constraint that "a" and "b" are the same type.
 1216    /// </summary>
 262461217    private void ConstrainSubtypeRelation_Equal(Type a, Type b, TypeConstraint.ErrorMsg errMsg) {
 1218      Contract.Requires(a != null);
 1219      Contract.Requires(b != null);
 1220      Contract.Requires(errMsg != null);
 1221
 262461222      var proxy = a.Normalize() as TypeProxy;
 386231223      if (proxy != null && proxy.T == null && !Reaches(b, proxy, 1, new HashSet<TypeProxy>())) {
 123771224        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01225          Options.OutputWriter.WriteLine("DEBUG: (invariance) assigning proxy {0}.T := {1}", proxy, b);
 01226        }
 123771227        proxy.T = b;
 123771228      }
 262461229      proxy = b.Normalize() as TypeProxy;
 270951230      if (proxy != null && proxy.T == null && !Reaches(a, proxy, 1, new HashSet<TypeProxy>())) {
 8491231        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01232          Options.OutputWriter.WriteLine("DEBUG: (invariance) assigning proxy {0}.T := {1}", proxy, a);
 01233        }
 8491234        proxy.T = a;
 8491235      }
 1236
 262461237      ConstrainSubtypeRelation(a, b, errMsg, true);
 262461238      ConstrainSubtypeRelation(b, a, errMsg, true);
 262461239    }
 1240
 1241    /// <summary>
 1242    /// Adds the subtyping constraint that "sub" is a subtype of "super".
 1243    /// If this constraint seems feasible, returns "true".  Otherwise, prints error message (either "errMsg" or somethin
 1244    /// more specific) and returns "false".
 1245    /// Note, if in doubt, this method can return "true", because the constraints will be checked for sure at a later st
 1246    /// </summary>
 12921371247    private bool ConstrainSubtypeRelation(Type super, Type sub, TypeConstraint.ErrorMsg errMsg, bool keepConstraints = f
 1248      Contract.Requires(sub != null);
 1249      Contract.Requires(super != null);
 1250      Contract.Requires(errMsg != null);
 1251
 16962391252      if (!keepConstraints && super is InferredTypeProxy) {
 4041021253        var ip = (InferredTypeProxy)super;
 5317201254        if (ip.KeepConstraints) {
 1276181255          keepConstraints = true;
 1276181256        }
 4041021257      }
 16008411258      if (!keepConstraints && sub is InferredTypeProxy) {
 3087041259        var ip = (InferredTypeProxy)sub;
 3237951260        if (ip.KeepConstraints) {
 150911261          keepConstraints = true;
 150911262        }
 3087041263      }
 1264
 12921371265      super = super.NormalizeExpand(keepConstraints);
 12921371266      sub = sub.NormalizeExpand(keepConstraints);
 12921371267      var c = new TypeConstraint(super, sub, errMsg, keepConstraints);
 12921371268      AllTypeConstraints.Add(c);
 12921371269      return ConstrainSubtypeRelation_Aux(super, sub, c, keepConstraints, allowDecisions);
 12921371270    }
 12921371271    private bool ConstrainSubtypeRelation_Aux(Type super, Type sub, TypeConstraint c, bool keepConstraints, bool allowDe
 1272      Contract.Requires(sub != null);
 1273      Contract.Requires(!(sub is TypeProxy) || ((TypeProxy)sub).T == null);  // caller is expected to have Normalized aw
 1274      Contract.Requires(super != null);
 1275      Contract.Requires(!(super is TypeProxy) || ((TypeProxy)super).T == null);  // caller is expected to have Normalize
 1276      Contract.Requires(c != null);
 1277
 16725261278      if (object.ReferenceEquals(super, sub)) {
 3803891279        return true;
 10665371280      } else if (super is TypeProxy && sub is TypeProxy) {
 1281        // both are proxies
 1547891282        ((TypeProxy)sub).AddSupertype(c);
 1547891283        ((TypeProxy)super).AddSubtype(c);
 1547891284        return true;
 10744711285      } else if (sub is TypeProxy) {
 3175121286        var proxy = (TypeProxy)sub;
 3175121287        proxy.AddSupertype(c);
 3175121288        AssignKnownEnd(proxy, keepConstraints, allowDecisions);
 3175121289        return true;
 6183031290      } else if (super is TypeProxy) {
 1788561291        var proxy = (TypeProxy)super;
 1788561292        proxy.AddSubtype(c);
 1788561293        AssignKnownEnd(proxy, keepConstraints, allowDecisions);
 1788561294        return true;
 2605911295      } else {
 1296        // two non-proxy types
 1297        // set "headSymbolsAgree" to "false" if it's clear the head symbols couldn't be the same; "true" means they may 
 2605911298        bool headSymbolsAgree = Type.IsHeadSupertypeOf(super.NormalizeExpand(keepConstraints), sub);
 2605911299        if (!headSymbolsAgree) {
 01300          c.FlagAsError(this);
 01301          return false;
 1302        }
 1303        // TODO: inspect type parameters in order to produce some error messages sooner
 2605911304        return true;
 1305      }
 12921371306    }
 1307
 1308    /// <summary>
 1309    /// "root" says that the type is a non-artificial type (that is, not an ArtificialType) with no proper supertypes.
 1310    /// "leaf" says that the only possible proper subtypes are subset types of the type. Thus, the only
 1311    /// types that are not leaf types are traits and artificial types.
 1312    /// The "headIs" versions speak only about the head symbols, so it is possible that the given
 1313    /// type arguments would change the root/leaf status of the entire type.
 1314    /// </summary>
 542737821315    void DetermineRootLeaf(Type t, out bool isRoot, out bool isLeaf, out bool headIsRoot, out bool headIsLeaf) {
 1316      Contract.Requires(t != null);
 1317      Contract.Ensures(!Contract.ValueAtReturn(out isRoot) || Contract.ValueAtReturn(out headIsRoot)); // isRoot ==> hea
 1318      Contract.Ensures(!Contract.ValueAtReturn(out isLeaf) || Contract.ValueAtReturn(out headIsLeaf)); // isLeaf ==> hea
 542737821319      t = t.NormalizeExpandKeepConstraints();
 542740881320      if (t.IsObjectQ) {
 6121321        isRoot = true; isLeaf = false;
 6121322        headIsRoot = true; headIsLeaf = false;
 542737821323      } else if (t is ArrowType) {
 01324        var arr = (ArrowType)t;
 01325        headIsRoot = true; headIsLeaf = true;  // these are definitely true
 01326        isRoot = true; isLeaf = true;  // set these to true until proven otherwise
 01327        Contract.Assert(arr.Arity + 1 == arr.TypeArgs.Count);
 01328        for (int i = 0; i < arr.TypeArgs.Count; i++) {
 01329          var arg = arr.TypeArgs[i];
 01330          DetermineRootLeaf(arg, out var r, out var l, out _, out _);
 01331          if (i < arr.Arity) {
 01332            isRoot &= l; isLeaf &= r;  // argument types are contravariant
 01333          } else {
 01334            isRoot &= r; isLeaf &= l;  // result type is covariant
 01335          }
 01336        }
 555998841337      } else if (t is UserDefinedType) {
 13264081338        var udt = (UserDefinedType)t;
 13264081339        var cl = udt.ResolvedClass;
 26528161340        if (cl != null) {
 13310641341          if (cl is TypeParameter) {
 46561342            var tp = udt.AsTypeParameter;
 46561343            Contract.Assert(tp != null);
 93121344            headIsRoot = true; headIsLeaf = true;  // all type parameters are non-variant
 21882891345          } else if (cl is SubsetTypeDecl) {
 17237621346            headIsRoot = false; headIsLeaf = true;
 13217521347          } else if (cl is NewtypeDecl) {
 01348            headIsRoot = true; headIsLeaf = true;
 4598711349          } else if (cl is TraitDecl) {
 01350            headIsRoot = false; headIsLeaf = false;
 8338241351          } else if (cl is ClassDecl) {
 7479061352            headIsRoot = false; headIsLeaf = true;
 4598711353          } else if (cl is AbstractTypeDecl) {
 01354            headIsRoot = true; headIsLeaf = true;
 859181355          } else if (cl is InternalTypeSynonymDecl) {
 01356            Contract.Assert(object.ReferenceEquals(t, t.NormalizeExpand())); // should be opaque in scope
 01357            headIsRoot = true; headIsLeaf = true;
 859181358          } else {
 859181359            Contract.Assert(cl is DatatypeDecl);
 1718361360            headIsRoot = true; headIsLeaf = true;
 859181361          }
 1362          // for "isRoot" and "isLeaf", also take into consideration the root/leaf status of type arguments
 26528161363          isRoot = headIsRoot; isLeaf = headIsLeaf;
 13264081364          Contract.Assert(udt.TypeArgs.Count == cl.TypeArgs.Count);
 68570761365          for (int i = 0; i < udt.TypeArgs.Count; i++) {
 14014201366            var variance = cl.TypeArgs[i].Variance;
 15425071367            if (variance != TypeParameter.TPVariance.Non) {
 1410871368              DetermineRootLeaf(udt.TypeArgs[i], out var r, out var l, out _, out _);
 1369              // isRoot and isLeaf aren't duals, so Co and Contra require separate consideration beyond inversion.
 1410871370              switch (variance) {
 5643481371                case TypeParameter.TPVariance.Co: { isRoot &= r; isLeaf &= l; break; }
 1372                // A invariably constructible subtype becomes a supertype, and thus the enclosing type is never a root.
 01373                case TypeParameter.TPVariance.Contra: { isRoot &= false; isLeaf &= r; break; }
 1374              }
 1410871375            }
 14014201376          }
 13264081377        } else {
 01378          isRoot = false; isLeaf = false;  // don't know
 01379          headIsRoot = false; headIsLeaf = false;
 01380        }
 551523131381      } else if (t.IsBoolType || t.IsCharType || t.IsIntegerType || t.IsRealType || t.AsNewtype != null || t.IsBitVector
 17576741382        isRoot = true; isLeaf = true;
 17576741383        headIsRoot = true; headIsLeaf = true;
 529470681384      } else if (t is ArtificialType) {
 01385        isRoot = false; isLeaf = false;
 01386        headIsRoot = false; headIsLeaf = false;
 521025501387      } else if (t is MapType) {  // map, imap
 343191388        Contract.Assert(t.TypeArgs.Count == 2);
 343191389        DetermineRootLeaf(t.TypeArgs[0], out var r0, out _, out _, out _);
 343191390        DetermineRootLeaf(t.TypeArgs[1], out var r1, out _, out _, out _);
 686381391        isRoot = r0 & r1; isLeaf = r0 & r1;  // map types are covariant in both type arguments
 686381392        headIsRoot = true; headIsLeaf = true;
 521567921393      } else if (t is CollectionType) {  // set, iset, multiset, seq
 885611394        Contract.Assert(t.TypeArgs.Count == 1);
 885611395        DetermineRootLeaf(t.TypeArgs[0], out isRoot, out isLeaf, out _, out _);  // type is covariant is type argument
 1771221396        headIsRoot = true; headIsLeaf = true;
 520339121397      } else {
 1038907021398        isRoot = false; isLeaf = false;  // don't know
 1038907021399        headIsRoot = false; headIsLeaf = false;
 519453511400      }
 542737821401    }
 1402
 3061403    int _recursionDepth = 0;
 4457681404    private bool AssignProxyAndHandleItsConstraints(TypeProxy proxy, Type t, bool keepConstraints = false) {
 1405      Contract.Requires(proxy != null);
 1406      Contract.Requires(proxy.T == null);
 1407      Contract.Requires(t != null);
 1408      Contract.Requires(!(t is TypeProxy));
 1409      Contract.Requires(!(t is ArtificialType));
 4457681410      if (_recursionDepth == 20000) {
 01411        Contract.Assume(false);  // possible infinite recursion
 01412      }
 4457681413      _recursionDepth++;
 4457681414      var b = AssignProxyAndHandleItsConstraints_aux(proxy, t, keepConstraints);
 4457681415      _recursionDepth--;
 4457681416      return b;
 4457681417    }
 1418    /// <summary>
 1419    /// This method is called if "proxy" is an unassigned proxy and "t" is a type whose head symbol is known.
 1420    /// It always sets "proxy.T" to "t".
 1421    /// Then, it deals with the constraints of "proxy" as follows:
 1422    /// * If the constraint compares "t" with a non-proxy with a head comparable with that of "t",
 1423    ///   then add constraints that the type arguments satisfy the desired subtyping constraint
 1424    /// * If the constraint compares "t" with a non-proxy with a head not comparable with that of "t",
 1425    ///   then report an error
 1426    /// * If the constraint compares "t" with a proxy, then (depending on the constraint and "t") attempt
 1427    ///   to recursively set it
 1428    /// After this process, the proxy's .Supertypes and .Subtypes lists of constraints are no longer needed.
 1429    /// If anything is found to be infeasible, "false" is returned (and the propagation may be interrupted);
 1430    /// otherwise, "true" is returned.
 1431    /// </summary>
 4457681432    private bool AssignProxyAndHandleItsConstraints_aux(TypeProxy proxy, Type t, bool keepConstraints = false) {
 1433      Contract.Requires(proxy != null);
 1434      Contract.Requires(proxy.T == null);
 1435      Contract.Requires(t != null);
 1436      Contract.Requires(!(t is TypeProxy));
 1437      Contract.Requires(!(t is ArtificialType));
 1438
 4457681439      t = keepConstraints ? t.Normalize() : t.NormalizeExpand();
 1440      // never violate the type constraint of a literal expression
 4457681441      var followedRequestedAssignment = true;
 20383361442      foreach (var su in proxy.Supertypes) {
 4445121443        if (su is IntVarietiesSupertype) {
 1474031444          var fam = TypeProxy.GetFamily(t);
 2948061445          if (fam == TypeProxy.Family.IntLike || fam == TypeProxy.Family.BitVector || fam == TypeProxy.Family.Ordinal) {
 1446            // good, let's continue with the request to equate the proxy with t
 1447            // unless...
 1474031448            if (t != t.NormalizeExpand()) {
 1449              // force the type to be a base type
 01450              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01451                Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, t.Normal
 01452              }
 01453              t = t.NormalizeExpand();
 01454              followedRequestedAssignment = false;
 01455            }
 1474031456          } else {
 1457            // hijack the setting of proxy; to do that, we decide on a particular int variety now
 01458            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01459              Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, Type.Int);
 01460            }
 01461            t = Type.Int;
 01462            followedRequestedAssignment = false;
 01463          }
 1474031464          break;
 1925981465        } else if (su is RealVarietiesSupertype) {
 857841466          if (TypeProxy.GetFamily(t) == TypeProxy.Family.RealLike) {
 1467            // good, let's continue with the request to equate the proxy with t
 1468            // unless...
 428921469            if (t != t.NormalizeExpand()) {
 1470              // force the type to be a base type
 01471              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01472                Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, t.Normal
 01473              }
 01474              t = t.NormalizeExpand();
 01475              followedRequestedAssignment = false;
 01476            }
 428921477          } else {
 1478            // hijack the setting of proxy; to do that, we decide on a particular real variety now
 01479            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01480              Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, Type.Real)
 01481            }
 01482            t = Type.Real;
 01483            followedRequestedAssignment = false;
 01484          }
 428921485          break;
 1486        }
 1068141487      }
 1488      // set proxy.T right away, so that we can freely recurse without having to worry about infinite recursion
 4457681489      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01490        Options.OutputWriter.WriteLine("DEBUG: setting proxy {0}.T := {1}", proxy, t);
 01491      }
 4457681492      proxy.T = t;
 1493
 1494      // check feasibility
 4457681495      DetermineRootLeaf(t, out var isRoot, out var isLeaf, out _, out _);
 1496      // propagate up
 26657581497      foreach (var c in proxy.SupertypeConstraints) {
 4428181498        var u = keepConstraints ? c.Super.NormalizeExpandKeepConstraints() : c.Super.NormalizeExpand();
 8768431499        if (!(u is TypeProxy)) {
 4340251500          ImposeSubtypingConstraint(u, t, c.ErrMsg);
 4511071501        } else if (isRoot) {
 1502          // If t is a root, we might as well constrain u now.  Otherwise, we'll wait until the .Subtype constraint of u
 82891503          AssignProxyAndHandleItsConstraints((TypeProxy)u, t, keepConstraints);
 82891504        }
 4428181505      }
 1506      // propagate down
 22927291507      foreach (var c in proxy.SubtypeConstraints) {
 3184751508        var u = keepConstraints ? c.Sub.NormalizeExpandKeepConstraints() : c.Sub.NormalizeExpand();
 3184751509        Contract.Assert(!TypeProxy.IsSupertypeOfLiteral(u));  // these should only appear among .Supertypes
 5137131510        if (!(u is TypeProxy)) {
 1952381511          ImposeSubtypingConstraint(t, u, c.ErrMsg);
 4399631512        } else if (isLeaf) {
 1513          // If t is a leaf (no pun intended), we might as well constrain u now.  Otherwise, we'll wait until the .Super
 1214881514          AssignProxyAndHandleItsConstraints((TypeProxy)u, t, keepConstraints);
 1214881515        }
 3184751516      }
 1517
 4457681518      return followedRequestedAssignment;
 4457681519    }
 1520
 1521    /// <summary>
 1522    /// Impose constraints that "sub" is a subtype of "super", returning "false" if this leads to an overconstrained sit
 1523    /// In most cases, "sub" being a subtype of "super" means that "sub" and "super" have the same head symbol and, ther
 1524    /// same number of type arguments. Depending on the polarities of the type parameters, the corresponding arguments
 1525    /// of "sub" and "super" must be in co-, in-, or contra-variant relationships to each other.
 1526    /// There are two ways "sub" can be a subtype of "super" without the two having the same head symbol.
 1527    /// One way is that "sub" is a subset type. In this case, the method starts by moving "sub" up toward "super".
 1528    /// The other way is that "super" is a trait (possibly
 1529    /// the trait "object").  By a current restriction in Dafny's type system, traits have no type parameters, so in thi
 1530    /// suffices to check that the head symbol of "super" is something that derives from "sub".
 1531    /// </summary>
 9063931532    private bool ImposeSubtypingConstraint(Type super, Type sub, TypeConstraint.ErrorMsg errorMsg) {
 1533      Contract.Requires(super != null && !(super is TypeProxy));
 1534      Contract.Requires(sub != null && !(sub is TypeProxy));
 1535      Contract.Requires(errorMsg != null);
 9063931536      super = super.NormalizeExpandKeepConstraints();
 9063931537      sub = sub.NormalizeExpandKeepConstraints();
 9063931538      List<int> polarities = ConstrainTypeHead_Recursive(super, ref sub);
 9063931539      if (polarities == null) {
 01540        errorMsg.FlagAsError(this);
 01541        return false;
 1542      }
 9063931543      bool keepConstraints = KeepConstraints(super, sub);
 9063931544      var p = polarities.Count;
 9063931545      Contract.Assert(p == super.TypeArgs.Count);  // postcondition of ConstrainTypeHead
 9063931546      Contract.Assert(p == 0 || sub.TypeArgs.Count == super.TypeArgs.Count);  // postcondition of ConstrainTypeHead
 23722711547      for (int i = 0; i < p; i++) {
 1864951548        var pol = polarities[i];
 1864951549        var tp = p == 1 ? "" : " " + i;
 1864951550        var errMsg = new TypeConstraint.ErrorMsgWithBase(errorMsg,
 1864951551          pol < 0 ? "contravariant type parameter{0} would require {1} <: {2}" :
 1864951552          pol > 0 ? "covariant type parameter{0} would require {2} <: {1}" :
 1864951553          "non-variant type parameter{0} would require {1} = {2}",
 1864951554          tp, super.TypeArgs[i], sub.TypeArgs[i]);
 3729901555        if (pol >= 0) {
 1864951556          if (!ConstrainSubtypeRelation(super.TypeArgs[i], sub.TypeArgs[i], errMsg, keepConstraints)) {
 01557            return false;
 1558          }
 1864951559        }
 2019331560        if (pol <= 0) {
 154381561          if (!ConstrainSubtypeRelation(sub.TypeArgs[i], super.TypeArgs[i], errMsg, keepConstraints)) {
 01562            return false;
 1563          }
 154381564        }
 1864951565      }
 9063931566      return true;
 9063931567    }
 1568
 1569    /// <summary>
 1570    /// This is a more liberal version of "ConstrainTypeHead" below. It is willing to move "sub"
 1571    /// upward toward its parents until it finds a head that matches "super", if any.
 1572    /// </summary>
 9064031573    private static List<int> ConstrainTypeHead_Recursive(Type super, ref Type sub) {
 1574      Contract.Requires(super != null);
 1575      Contract.Requires(sub != null);
 1576
 9064031577      super = super.NormalizeExpandKeepConstraints();
 9064031578      sub = sub.NormalizeExpandKeepConstraints();
 1579
 9064031580      var polarities = ConstrainTypeHead(super, sub);
 18127961581      if (polarities != null) {
 9063931582        return polarities;
 1583      }
 1584
 501585      foreach (var subParentType in sub.ParentTypes()) {
 101586        sub = subParentType;
 101587        polarities = ConstrainTypeHead_Recursive(super, ref sub);
 201588        if (polarities != null) {
 101589          return polarities;
 1590        }
 01591      }
 1592
 01593      return null;
 9064031594    }
 1595
 1596    /// <summary>
 1597    /// Determines if the head of "sub" can be a subtype of "super".
 1598    /// If this is not possible, null is returned.
 1599    /// If it is possible, return a list of polarities, one for each type argument of "sub".  Polarities
 1600    /// indicate:
 1601    ///     +1  co-variant
 1602    ///      0  invariant
 1603    ///     -1  contra-variant
 1604    /// "sub" is of some type that can (in general) have type parameters.
 1605    /// See also note about Dafny's current type system in the description of method "ImposeSubtypingConstraint".
 1606    /// </summary>
 9064031607    private static List<int> ConstrainTypeHead(Type super, Type sub) {
 1608      Contract.Requires(super != null && !(super is TypeProxy));
 1609      Contract.Requires(sub != null && !(sub is TypeProxy));
 12332781610      if (super is IntVarietiesSupertype) {
 3268751611        var famSub = TypeProxy.GetFamily(sub);
 6537501612        if (famSub == TypeProxy.Family.IntLike || famSub == TypeProxy.Family.BitVector || famSub == TypeProxy.Family.Ord
 3268751613          return new List<int>();
 01614        } else {
 01615          return null;
 1616        }
 6649621617      } else if (super is RealVarietiesSupertype) {
 1708681618        if (TypeProxy.GetFamily(sub) == TypeProxy.Family.RealLike || super.Equals(sub)) {
 854341619          return new List<int>();
 01620        } else {
 01621          return null;
 1622        }
 1623      }
 4940941624      switch (TypeProxy.GetFamily(super)) {
 1625        case TypeProxy.Family.Bool:
 1626        case TypeProxy.Family.Char:
 1627        case TypeProxy.Family.IntLike:
 1628        case TypeProxy.Family.RealLike:
 1629        case TypeProxy.Family.Ordinal:
 1630        case TypeProxy.Family.BitVector:
 7314201631          if (super.Equals(sub)) {
 3657101632            if (sub is UserDefinedType subUserDefinedType) {
 01633              return subUserDefinedType.ResolvedClass.TypeArgs.ConvertAll(tp => TypeParameter.Direction(tp.Variance));
 3657101634            } else {
 3657101635              return new List<int>();
 1636            }
 01637          } else {
 01638            return null;
 1639          }
 1640        case TypeProxy.Family.ValueType:
 1641        case TypeProxy.Family.Ref:
 1642        case TypeProxy.Family.Opaque:
 1283841643          break;  // more elaborate work below
 1644        case TypeProxy.Family.Unknown:
 01645          return null;
 1646        default:
 01647          Contract.Assert(false);  // unexpected type (the precondition of ConstrainTypeHead says "no proxies")
 01648          return null;  // please compiler
 1649      }
 1415401650      if (super is SetType) {
 131561651        var tt = (SetType)super;
 131561652        var uu = sub as SetType;
 131561653        return uu != null && tt.Finite == uu.Finite ? new List<int> { 1 } : null;
 1458411654      } else if (super is SeqType) {
 306131655        return sub is SeqType ? new List<int> { 1 } : null;
 1037301656      } else if (super is MultiSetType) {
 191151657        return sub is MultiSetType ? new List<int> { 1 } : null;
 890041658      } else if (super is MapType) {
 235041659        var tt = (MapType)super;
 235041660        var uu = sub as MapType;
 235041661        return uu != null && tt.Finite == uu.Finite ? new List<int> { 1, 1 } : null;
 419961662      } else if (super.IsObjectQ) {
 01663        return sub.IsRefType ? new List<int>() : null;
 419961664      } else {
 1665        // The only remaining cases are that "super" is a (co)datatype, abstract type, or non-object trait/class.
 1666        // In each of these cases, "super" is a UserDefinedType.
 419961667        var udfSuper = (UserDefinedType)super;
 419961668        var clSuper = udfSuper.ResolvedClass;
 419961669        if (clSuper == null) {
 01670          Contract.Assert(super.TypeArgs.Count == 0);
 01671          if (super.IsTypeParameter) {
 1672            // we're looking at a type parameter
 01673            return super.AsTypeParameter == sub.AsTypeParameter ? new List<int>() : null;
 01674          } else {
 01675            Contract.Assert(super.IsInternalTypeSynonym);
 01676            return super.AsInternalTypeSynonym == sub.AsInternalTypeSynonym ? new List<int>() : null;
 1677          }
 1678        }
 419961679        var udfSub = sub as UserDefinedType;
 419961680        var clSub = udfSub == null ? null : udfSub.ResolvedClass;
 419961681        if (clSub == null) {
 01682          return null;
 839821683        } else if (clSuper == clSub) {
 1684          // good
 419861685          var polarities = new List<int>();
 419861686          Contract.Assert(clSuper.TypeArgs.Count == udfSuper.TypeArgs.Count);
 419861687          Contract.Assert(clSuper.TypeArgs.Count == udfSub.TypeArgs.Count);
 3557671688          foreach (var tp in clSuper.TypeArgs) {
 766031689            var polarity = TypeParameter.Direction(tp.Variance);
 766031690            polarities.Add(polarity);
 766031691          }
 1692
 419861693          return polarities;
 101694        } else if (udfSub.IsRefType && super.IsObjectQ) {
 01695          return new List<int>();
 101696        } else if (udfSub.IsNonNullRefType && super.IsObject) {
 01697          return new List<int>();
 101698        } else {
 101699          return null;
 1700        }
 1701      }
 9064031702    }
 9063931703    private static bool KeepConstraints(Type super, Type sub) {
 1704      Contract.Requires(super != null && !(super is TypeProxy));
 1705      Contract.Requires(sub != null && !(sub is TypeProxy));
 12332681706      if (super is IntVarietiesSupertype) {
 3268751707        return false;
 6649521708      } else if (super is RealVarietiesSupertype) {
 854341709        return false;
 1710      }
 4940841711      switch (TypeProxy.GetFamily(super)) {
 1712        case TypeProxy.Family.Bool:
 1713        case TypeProxy.Family.Char:
 1714        case TypeProxy.Family.IntLike:
 1715        case TypeProxy.Family.RealLike:
 1716        case TypeProxy.Family.Ordinal:
 1717        case TypeProxy.Family.BitVector:
 3657101718          return false;
 1719        case TypeProxy.Family.ValueType:
 1720        case TypeProxy.Family.Ref:
 1721        case TypeProxy.Family.Opaque:
 1283741722          break;  // more elaborate work below
 1723        case TypeProxy.Family.Unknown:
 01724          return false;
 1725      }
 2147621726      if (super is SetType || super is SeqType || super is MultiSetType || super is MapType) {
 863881727        return true;
 419861728      } else if (super is ArrowType) {
 01729        return false;
 419861730      } else if (super.IsObjectQ) {
 01731        return false;
 419861732      } else {
 1733        // super is UserDefinedType
 419861734        return true;
 1735      }
 9063931736    }
 1737
 3061738    public List<TypeConstraint> AllTypeConstraints = new List<TypeConstraint>();
 3061739    public List<XConstraint> AllXConstraints = new List<XConstraint>();
 1740
 1741    public class XConstraint {
 1742      public readonly IToken tok;
 1743      public readonly string ConstraintName;
 1744      public readonly Type[] Types;
 1745      public readonly TypeConstraint.ErrorMsg errorMsg;
 10986901746      public XConstraint(IToken tok, string constraintName, Type[] types, TypeConstraint.ErrorMsg errMsg) {
 1747        Contract.Requires(tok != null);
 1748        Contract.Requires(constraintName != null);
 1749        Contract.Requires(types != null);
 1750        Contract.Requires(errMsg != null);
 5493451751        this.tok = tok;
 5493451752        ConstraintName = constraintName;
 5493451753        Types = types;
 5493451754        errorMsg = errMsg;
 5493451755      }
 1756
 01757      public override string ToString() {
 01758        var s = ConstraintName + ":";
 01759        foreach (var t in Types) {
 01760          s += " " + t;
 01761        }
 01762        return s;
 01763      }
 1764
 1765      /// <summary>
 1766      /// Tries to confirm the XConstraint.
 1767      /// If the XConstraint can be confirmed, or at least is plausible enough to have been converted into other type
 1768      /// constraints or more XConstraints, then "true" is returned and the out-parameters "convertedIntoOtherTypeConstr
 1769      /// and "moreXConstraints" are set to true accordingly.
 1770      /// If the XConstraint can be refuted, then an error message will be produced and "true" is returned (to indicate
 1771      /// that this XConstraint has finished serving its purpose).
 1772      /// If there's not enough information to confirm or refute the XConstraint, then "false" is returned.
 1773      /// </summary>
 160854131774      public bool Confirm(Resolver resolver, bool fullstrength, out bool convertedIntoOtherTypeConstraints, out bool mor
 1775        Contract.Requires(resolver != null);
 160854131776        convertedIntoOtherTypeConstraints = false;
 160854131777        moreXConstraints = false;
 160854131778        var t = Types[0].NormalizeExpand();
 270631371779        if (t is TypeProxy) {
 109777241780          switch (ConstraintName) {
 1781            case "Assignable":
 1782            case "Equatable":
 1783            case "EquatableArg":
 1784            case "Indexable":
 1785            case "Innable":
 1786            case "MultiIndexable":
 1787            case "IntOrORDINAL":
 1788              // have a go downstairs
 56630311789              break;
 1790            default:
 53146931791              return false;  // there's not enough information to confirm or refute this XConstraint
 1792          }
 56630311793        }
 1794        bool satisfied;
 107707201795        switch (ConstraintName) {
 103699611796          case "Assignable": {
 103699611797              Contract.Assert(t == t.Normalize());  // it's already been normalized above
 103699611798              var u = Types[1].NormalizeExpand();
 103699611799              if (CheckTypeInferenceVisitor.IsDetermined(t) &&
 103699611800                  (fullstrength
 103699611801                   || !ProxyWithNoSubTypeConstraint(u, resolver)
 103699611802                   || (u is TypeProxy
 103699611803                       && Types[0].NormalizeExpandKeepConstraints() is var t0constrained
 103699611804                       && (t0constrained.IsNonNullRefType || t0constrained.AsSubsetType != null)
 105972311805                       && resolver.HasApplicableNullableRefTypeConstraint(new HashSet<TypeProxy>() { (TypeProxy)u })))) 
 1806                // This is the best case.  We convert Assignable(t, u) to the subtype constraint base(t) :> u.
 2372581807                if (CheckTypeInferenceVisitor.IsDetermined(u) && t.IsSubtypeOf(u, false, true) && t.IsRefType) {
 1808                  // But we also allow cases where the rhs is a proper supertype of the lhs, and let the verifier
 1809                  // determine whether the rhs is provably an instance of the lhs.
 99881810                  resolver.ConstrainAssignable((NonProxyType)u, (NonProxyType)t, errorMsg, out moreXConstraints, fullstr
 2272701811                } else {
 2172821812                  resolver.ConstrainAssignable((NonProxyType)t, u, errorMsg, out moreXConstraints, fullstrength);
 2172821813                }
 2272701814                convertedIntoOtherTypeConstraints = true;
 2272701815                return true;
 101450191816              } else if (u.IsTypeParameter) {
 1817                // we need the constraint base(t) :> u, which for a type parameter t can happen iff t :> u
 23281818                resolver.ConstrainSubtypeRelation(t, u, errorMsg);
 23281819                convertedIntoOtherTypeConstraints = true;
 23281820                return true;
 101545131821              } else if (Type.FromSameHead(t, u, out var tUp, out var uUp)) {
 141501822                resolver.ConstrainAssignableTypeArgs(tUp, tUp.TypeArgs, uUp.TypeArgs, errorMsg, out moreXConstraints);
 141501823                return true;
 101262131824              } else if (fullstrength && t is NonProxyType) {
 1825                // We convert Assignable(t, u) to the subtype constraint base(t) :> u.
 01826                resolver.ConstrainAssignable((NonProxyType)t, u, errorMsg, out moreXConstraints, fullstrength);
 01827                convertedIntoOtherTypeConstraints = true;
 01828                return true;
 101262131829              } else if (fullstrength && u is NonProxyType) {
 1830                // We're willing to change "base(t) :> u" to the stronger constraint "t :> u" for the sake of making pro
 01831                resolver.ConstrainSubtypeRelation(t, u, errorMsg);
 01832                convertedIntoOtherTypeConstraints = true;
 01833                return true;
 1834              }
 1835              // There's not enough information to say anything
 101262131836              return false;
 1837            }
 1838          case "NumericType":
 01839            satisfied = t.IsNumericBased();
 01840            break;
 1841          case "IntegerType":
 68611842            satisfied = t.IsNumericBased(Type.NumericPersuasion.Int);
 68611843            break;
 1844          case "IsBitvector":
 01845            satisfied = t.IsBitVectorType;
 01846            break;
 1847          case "IsRefType":
 01848            satisfied = t.IsRefType;
 01849            break;
 1850          case "IsNullableRefType":
 6121851            satisfied = t.IsRefType && !t.IsNonNullRefType;
 6121852            break;
 1853          case "Orderable_Lt":
 174651854            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SeqType ||
 174651855            break;
 1856          case "Orderable_Gt":
 198021857            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SetType ||
 198021858            break;
 01859          case "RankOrderable": {
 01860              var u = Types[1].NormalizeExpand();
 01861              if (u is TypeProxy) {
 01862                return false;  // not enough information
 1863              }
 01864              satisfied = (t.IsIndDatatype || t.IsTypeParameter) && u.IsIndDatatype;
 01865              break;
 1866            }
 1867          case "Plussable":
 30311868            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SeqType ||
 30311869            break;
 1870          case "Minusable":
 25861871            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SetType ||
 25861872            break;
 1873          case "Mullable":
 6831874            satisfied = t.IsNumericBased() || t.IsBitVectorType || t is SetType || t is MultiSetType;
 6831875            break;
 1876          case "IntOrORDINAL":
 01877            if (!(t is TypeProxy)) {
 01878              if (TernaryExpr.PrefixEqUsesNat) {
 01879                satisfied = t.IsNumericBased(Type.NumericPersuasion.Int);
 01880              } else {
 01881                satisfied = t.IsNumericBased(Type.NumericPersuasion.Int) || t.IsBigOrdinalType;
 01882              }
 01883            } else if (fullstrength) {
 01884              var proxy = (TypeProxy)t;
 01885              if (TernaryExpr.PrefixEqUsesNat) {
 01886                resolver.AssignProxyAndHandleItsConstraints(proxy, Type.Int);
 01887              } else {
 1888                // let's choose ORDINAL over int
 01889                resolver.AssignProxyAndHandleItsConstraints(proxy, Type.BigOrdinal);
 01890              }
 01891              convertedIntoOtherTypeConstraints = true;
 01892              satisfied = true;
 01893            } else {
 01894              return false;
 1895            }
 01896            break;
 1897          case "NumericOrBitvector":
 314121898            satisfied = t.IsNumericBased() || t.IsBitVectorType;
 314121899            break;
 1900          case "NumericOrBitvectorOrCharOrORDINAL":
 01901            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsCharType || t.IsBigOrdinalType;
 01902            break;
 1903          case "IntLikeOrBitvector":
 14801904            satisfied = t.IsNumericBased(Type.NumericPersuasion.Int) || t.IsBitVectorType;
 14801905            break;
 1906          case "BooleanBits":
 2121907            satisfied = t.IsBoolType || t.IsBitVectorType;
 2121908            break;
 1909          case "Sizeable":
 208821910            satisfied = (t is SetType && ((SetType)t).Finite) || t is MultiSetType || t is SeqType || (t is MapType && (
 208821911            break;
 1912          case "Disjointable":
 1821913            satisfied = t is SetType || t is MultiSetType;
 1821914            break;
 1915          case "MultiSetConvertible":
 28921916            satisfied = (t is SetType && ((SetType)t).Finite) || t is SeqType;
 57841917            if (satisfied) {
 28921918              Type elementType = ((CollectionType)t).Arg;
 28921919              var u = Types[1];  // note, it's okay if "u" is a TypeProxy
 28921920              var em = new TypeConstraint.ErrorMsgWithBase(errorMsg, "expecting element type {0} (got {1})", u, elementT
 28921921              resolver.ConstrainSubtypeRelation_Equal(elementType, u, em);
 28921922              convertedIntoOtherTypeConstraints = true;
 28921923            }
 28921924            break;
 1925          case "IsCoDatatype":
 01926            satisfied = t.IsCoDatatype;
 01927            break;
 1928          case "Indexable":
 603061929            if (!(t is TypeProxy)) {
 300531930              satisfied = t is SeqType || t is MultiSetType || t is MapType || (t.IsArrayType && t.AsArrayType.Dims == 1
 302531931            } else {
 1932              // t is a proxy, but perhaps it stands for something between "object" and "array<?>".  If so, we can add a
 1933              // that it does have the form "array<?>", since "object" would not be Indexable.
 2001934              var proxy = (TypeProxy)t;
 2001935              Type join = null;
 4001936              if (resolver.JoinOfAllSubtypes(proxy, ref join, new HashSet<TypeProxy>()) && join != null) {
 2001937                var headWithProxyArgs = Type.HeadWithProxyArgs(join);
 2001938                var tt = headWithProxyArgs.NormalizeExpand();
 2001939                satisfied = tt is SeqType || tt is MultiSetType || tt is MapType || (tt.IsArrayType && tt.AsArrayType.Di
 4001940                if (satisfied) {
 2001941                  resolver.AssignProxyAndHandleItsConstraints(proxy, headWithProxyArgs, true);
 2001942                  convertedIntoOtherTypeConstraints = true;
 2001943                }
 2001944              } else {
 01945                return false;  // we can't determine the answer
 1946              }
 2001947            }
 302531948            break;
 1949          case "MultiIndexable":
 31621950            if (!(t is TypeProxy)) {
 15811951              satisfied = t is SeqType || (t.IsArrayType && t.AsArrayType.Dims == 1);
 15811952            } else {
 1953              // t is a proxy, but perhaps it stands for something between "object" and "array<?>".  If so, we can add a
 1954              // that it does have the form "array<?>", since "object" would not be Indexable.
 01955              var proxy = (TypeProxy)t;
 01956              Type join = null;
 01957              if (resolver.JoinOfAllSubtypes(proxy, ref join, new HashSet<TypeProxy>()) && join != null) {
 01958                var headWithProxyArgs = Type.HeadWithProxyArgs(join);
 01959                var tt = headWithProxyArgs.NormalizeExpand();
 01960                satisfied = tt is SeqType || (tt.IsArrayType && tt.AsArrayType.Dims == 1);
 01961                if (satisfied) {
 01962                  resolver.AssignProxyAndHandleItsConstraints(proxy, headWithProxyArgs, true);
 01963                  convertedIntoOtherTypeConstraints = true;
 01964                }
 01965              } else {
 01966                return false;  // we can't determine the answer
 1967              }
 01968            }
 15811969            break;
 83131970          case "Innable": {
 83131971              var elementType = FindCollectionType(resolver.Options, t, true, new HashSet<TypeProxy>()) ?? FindCollectio
 166261972              if (elementType != null) {
 83131973                var u = Types[1];  // note, it's okay if "u" is a TypeProxy
 83131974                resolver.AddXConstraint(this.tok, "Equatable", elementType, u, new TypeConstraint.ErrorMsgWithBase(error
 83131975                moreXConstraints = true;
 83131976                return true;
 1977              }
 01978              if (t is TypeProxy) {
 01979                return false;  // not enough information to do anything
 1980              }
 01981              satisfied = false;
 01982              break;
 1983            }
 34951984          case "SeqUpdatable": {
 34951985              var xcWithExprs = (XConstraintWithExprs)this;
 34951986              var index = xcWithExprs.Exprs[0];
 34951987              var value = xcWithExprs.Exprs[1];
 50061988              if (t is SeqType) {
 15111989                var s = (SeqType)t;
 15111990                resolver.ConstrainToIntegerType(index, true, "sequence update requires integer- or bitvector-based index
 15111991                resolver.ConstrainSubtypeRelation(s.Arg, value.Type, value, "sequence update requires the value to have 
 54791992              } else if (t is MapType) {
 19841993                var s = (MapType)t;
 39681994                if (s.Finite) {
 19841995                  resolver.ConstrainSubtypeRelation(s.Domain, index.Type, index, "map update requires domain element to 
 19841996                  resolver.ConstrainSubtypeRelation(s.Range, value.Type, value, "map update requires the value to have t
 19841997                } else {
 01998                  resolver.ConstrainSubtypeRelation(s.Domain, index.Type, index, "imap update requires domain element to
 01999                  resolver.ConstrainSubtypeRelation(s.Range, value.Type, value, "imap update requires the value to have 
 02000                }
 19842001              } else if (t is MultiSetType) {
 02002                var s = (MultiSetType)t;
 02003                resolver.ConstrainSubtypeRelation(s.Arg, index.Type, index, "multiset update requires domain element to 
 02004                resolver.ConstrainToIntegerType(value, false, "multiset update requires integer-based numeric value (got
 02005              } else {
 02006                satisfied = false;
 02007                break;
 2008              }
 34952009              convertedIntoOtherTypeConstraints = true;
 34952010              return true;
 2011            }
 2012          case "ContainerIndex":
 2013            // The semantics of this XConstraint is that *if* the head is seq/array/map/multiset, then its element/domai
 2014            Type indexType;
 590062015            if (t is SeqType || t.IsArrayType) {
 255912016              resolver.ConstrainToIntegerType(errorMsg.Tok, Types[1], true, errorMsg);
 255912017              convertedIntoOtherTypeConstraints = true;
 255912018              return true;
 156482019            } else if (t is MapType) {
 78242020              indexType = ((MapType)t).Domain;
 78242021            } else if (t is MultiSetType) {
 02022              indexType = ((MultiSetType)t).Arg;
 02023            } else {
 2024              // some other head symbol; that's cool
 02025              return true;
 2026            }
 2027            // note, it's okay if "Types[1]" is a TypeProxy
 78242028            resolver.ConstrainSubtypeRelation(indexType, Types[1], errorMsg);  // use the same error message
 78242029            convertedIntoOtherTypeConstraints = true;
 78242030            return true;
 2031          case "ContainerResult":
 2032            // The semantics of this XConstraint is that *if* the head is seq/array/map/multiset, then the type of a sel
 2033            Type resultType;
 433422034            if (t is SeqType) {
 115082035              resultType = ((SeqType)t).Arg;
 443362036            } else if (t.IsArrayType) {
 125022037              resultType = UserDefinedType.ArrayElementType(t);
 281502038            } else if (t is MapType) {
 78242039              resultType = ((MapType)t).Range;
 78242040            } else if (t is MultiSetType) {
 02041              resultType = resolver.builtIns.Nat();
 02042            } else {
 2043              // some other head symbol; that's cool
 02044              return true;
 2045            }
 2046            // note, it's okay if "Types[1]" is a TypeProxy
 318342047            resolver.ConstrainSubtypeRelation(Types[1], resultType, errorMsg);
 318342048            convertedIntoOtherTypeConstraints = true;
 318342049            return true;
 868892050          case "Equatable": {
 868892051              t = Types[0].NormalizeExpandKeepConstraints();
 868892052              var u = Types[1].NormalizeExpandKeepConstraints();
 890092053              if (object.ReferenceEquals(t, u)) {
 21202054                return true;
 2055              }
 947252056              if (t is TypeProxy && u is TypeProxy) {
 99562057                return false;  // not enough information to do anything sensible
 1063252058              } else if (t is TypeProxy || u is TypeProxy) {
 2059                TypeProxy proxy;
 2060                Type other;
 473372061                if (t is TypeProxy) {
 158252062                  proxy = (TypeProxy)t;
 158252063                  other = u;
 315122064                } else {
 156872065                  proxy = (TypeProxy)u;
 156872066                  other = t;
 156872067                }
 459852068                if (other.IsNumericBased() || other.IsBitVectorType || other.IsBigOrdinalType) {
 144732069                  resolver.ConstrainSubtypeRelation(other.NormalizeExpand(), proxy, errorMsg, true);
 144732070                  convertedIntoOtherTypeConstraints = true;
 144732071                  return true;
 177062072                } else if (fullstrength) {
 2073                  // the following is rather aggressive
 6672074                  if (Resolver.TypeConstraintsIncludeProxy(other, proxy)) {
 02075                    return false;
 6672076                  } else {
 12792077                    if (other.IsRefType && resolver.HasApplicableNullableRefTypeConstraint_SubDirection(proxy)) {
 6122078                      other = other.NormalizeExpand();  // shave off all constraints
 6122079                    }
 6672080                    satisfied = resolver.AssignProxyAndHandleItsConstraints(proxy, other, true);
 6672081                    convertedIntoOtherTypeConstraints = true;
 6672082                    break;
 2083                  }
 163722084                } else {
 163722085                  return false;  // not enough information
 2086                }
 2087              }
 2088
 433012089              satisfied = Type.FromSameHead_Subtype(t, u, out var a, out var b);
 866022090              if (satisfied) {
 433012091                Contract.Assert(a.TypeArgs.Count == b.TypeArgs.Count);
 433012092                var cl = a is UserDefinedType ? ((UserDefinedType)a).ResolvedClass : null;
 1480722093                for (int i = 0; i < a.TypeArgs.Count; i++) {
 204902094                  resolver.AllXConstraints.Add(new XConstraint_EquatableArg(tok,
 204902095                    a.TypeArgs[i], b.TypeArgs[i],
 204902096                    a is CollectionType || (cl != null && cl.TypeArgs[i].Variance != TypeParameter.TPVariance.Non),
 204902097                    a.IsRefType,
 204902098                    errorMsg));
 204902099                  moreXConstraints = true;
 204902100                }
 433012101              }
 433012102              break;
 2103            }
 968692104          case "EquatableArg": {
 968692105              t = Types[0].NormalizeExpandKeepConstraints();
 968692106              var u = Types[1].NormalizeExpandKeepConstraints();
 968692107              var moreExactThis = (XConstraint_EquatableArg)this;
 982742108              if (t is TypeProxy && u is TypeProxy) {
 14052109                return false;  // not enough information to do anything sensible
 1687562110              } else if (t is TypeProxy || u is TypeProxy) {
 2111                TypeProxy proxy;
 2112                Type other;
 733122113                if (t is TypeProxy) {
 202114                  proxy = (TypeProxy)t;
 202115                  other = u;
 732922116                } else {
 732722117                  proxy = (TypeProxy)u;
 732722118                  other = t;
 732722119                }
 775872120                if (other.IsNumericBased() || other.IsBitVectorType || other.IsBigOrdinalType) {
 42952121                  resolver.ConstrainSubtypeRelation(other.NormalizeExpand(), proxy, errorMsg, true);
 42952122                  convertedIntoOtherTypeConstraints = true;
 42952123                  return true;
 699782124                } else if (fullstrength) {
 2125                  // the following is rather aggressive
 9812126                  if (Resolver.TypeConstraintsIncludeProxy(other, proxy)) {
 02127                    return false;
 9812128                  } else {
 9812129                    if (other.IsRefType && resolver.HasApplicableNullableRefTypeConstraint_SubDirection(proxy)) {
 02130                      other = other.NormalizeExpand();  // shave off all constraints
 02131                    }
 9812132                    satisfied = resolver.AssignProxyAndHandleItsConstraints(proxy, other, true);
 9812133                    convertedIntoOtherTypeConstraints = true;
 9812134                    break;
 2135                  }
 680162136                } else {
 680162137                  return false;  // not enough information
 2138                }
 2139              }
 221722140              if (moreExactThis.TreatTypeParamAsWild && (t.IsTypeParameter || u.IsTypeParameter || t.IsAbstractType || u
 02141                return true;
 249022142              } else if (!moreExactThis.AllowSuperSub) {
 27302143                resolver.ConstrainSubtypeRelation_Equal(t, u, errorMsg);
 27302144                convertedIntoOtherTypeConstraints = true;
 27302145                return true;
 2146              }
 2147
 2148              // okay if t<:u or u<:t (this makes type inference more manageable, though it is more liberal than one mig
 194422149              satisfied = Type.FromSameHead_Subtype(t, u, out var a, out var b);
 388842150              if (satisfied) {
 194422151                Contract.Assert(a.TypeArgs.Count == b.TypeArgs.Count);
 194422152                var cl = a is UserDefinedType ? ((UserDefinedType)a).ResolvedClass : null;
 597732153                for (int i = 0; i < a.TypeArgs.Count; i++) {
 69632154                  resolver.AllXConstraints.Add(new XConstraint_EquatableArg(tok,
 69632155                    a.TypeArgs[i], b.TypeArgs[i],
 69632156                    a is CollectionType || (cl != null && cl.TypeArgs[i].Variance != TypeParameter.TPVariance.Non),
 69632157                    false,
 69632158                    errorMsg));
 69632159                  moreXConstraints = true;
 69632160                }
 194422161              }
 194422162              break;
 2163            }
 02164          case "Freshable": {
 02165              var collType = t.AsCollectionType;
 02166              if (collType is SetType || collType is SeqType) {
 02167                t = collType.Arg.NormalizeExpand();
 02168              }
 02169              if (t is TypeProxy) {
 02170                return false;  // there is not enough information
 2171              }
 02172              satisfied = t.IsRefType;
 02173              break;
 2174            }
 102175          case "ModifiesFrame": {
 102176              var u = Types[1].NormalizeExpand();  // eventual ref type
 102177              var collType = t is MapType ? null : t.AsCollectionType;
 102178              if (collType != null) {
 02179                t = collType.Arg.NormalizeExpand();
 02180              }
 102181              if (t is TypeProxy) {
 02182                if (collType != null) {
 2183                  // we know enough to convert into a subtyping constraint
 02184                  resolver.AddXConstraint(Token.NoToken/*bogus, but it seems this token would be used only when integers
 02185                  moreXConstraints = true;
 02186                  resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02187                  moreXConstraints = true;
 02188                  convertedIntoOtherTypeConstraints = true;
 02189                  return true;
 02190                } else {
 02191                  return false;  // there is not enough information
 2192                }
 2193              }
 202194              if (t.IsRefType) {
 102195                resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 102196                convertedIntoOtherTypeConstraints = true;
 102197                return true;
 2198              }
 02199              satisfied = false;
 02200              break;
 2201            }
 02202          case "ReadsFrame": {
 02203              var u = Types[1].NormalizeExpand();  // eventual ref type
 02204              var arrTy = t.AsArrowType;
 02205              if (arrTy != null) {
 02206                t = arrTy.Result.NormalizeExpand();
 02207              }
 02208              var collType = t is MapType ? null : t.AsCollectionType;
 02209              if (collType != null) {
 02210                t = collType.Arg.NormalizeExpand();
 02211              }
 02212              if (t is TypeProxy) {
 02213                if (collType != null) {
 2214                  // we know enough to convert into a subtyping constraint
 02215                  resolver.AddXConstraint(Token.NoToken/*bogus, but it seems this token would be used only when integers
 02216                  resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02217                  moreXConstraints = true;
 02218                  convertedIntoOtherTypeConstraints = true;
 02219                  return true;
 02220                } else {
 02221                  return false;  // there is not enough information
 2222                }
 2223              }
 02224              if (t.IsRefType && (arrTy == null || collType != null)) {
 02225                resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02226                convertedIntoOtherTypeConstraints = true;
 02227                return true;
 2228              }
 02229              satisfied = false;
 02230              break;
 2231            }
 2232          default:
 02233            Contract.Assume(false);  // unknown XConstraint
 02234            return false;  // to please the compiler
 2235        }
 2043252236        if (!satisfied) {
 02237          errorMsg.FlagAsError(resolver);
 02238        }
 2043252239        return true;  // the XConstraint has served its purpose
 160854132240      }
 2241
 47219922242      public bool ProxyWithNoSubTypeConstraint(Type u, Resolver resolver) {
 2243        Contract.Requires(u != null);
 2244        Contract.Requires(resolver != null);
 47219922245        var proxy = u as TypeProxy;
 92195612246        if (proxy != null) {
 44997112247          if (proxy.SubtypeConstraints.Any()) {
 21422248            return false;
 2249          }
 -9663890652250          foreach (var xc in resolver.AllXConstraints) {
 11050315902251            if (xc.ConstraintName == "Assignable" && xc.Types[0] == proxy) {
 7052252              return false;
 2253            }
 11050301802254          }
 44947222255          return true;
 2256        }
 2244232257        return false;
 47219922258      }
 2259
 02260      internal bool CouldBeAnything() {
 02261        return Types.All(t => t.NormalizeExpand() is TypeProxy);
 02262      }
 2263
 2264      /// <summary>
 2265      /// If "t" or any type among its transitive sub/super-types (depending on "towardsSub")
 2266      /// is a collection type, then returns the element/domain type of that collection.
 2267      /// Otherwise, returns null.
 2268      /// </summary>
 83132269      Type FindCollectionType(DafnyOptions options, Type t, bool towardsSub, ISet<TypeProxy> visited) {
 2270        Contract.Requires(t != null);
 2271        Contract.Requires(visited != null);
 83132272        t = t.NormalizeExpand();
 83132273        if (options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02274          options.OutputWriter.WriteLine("DEBUG: FindCollectionType({0}, {1})", t, towardsSub ? "sub" : "super");
 02275        }
 166262276        if (t is CollectionType) {
 83132277          if (options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02278            options.OutputWriter.WriteLine("DEBUG: FindCollectionType({0}) = {1}", t, ((CollectionType)t).Arg);
 02279          }
 83132280          return ((CollectionType)t).Arg;
 2281        }
 02282        var proxy = t as TypeProxy;
 02283        if (proxy == null || visited.Contains(proxy)) {
 02284          return null;
 2285        }
 02286        visited.Add(proxy);
 02287        foreach (var sub in towardsSub ? proxy.Subtypes : proxy.Supertypes) {
 02288          var e = FindCollectionType(options, sub, towardsSub, visited);
 02289          if (e != null) {
 02290            return e;
 2291          }
 02292        }
 02293        return null;
 83132294      }
 2295    }
 2296
 2297    public class XConstraintWithExprs : XConstraint {
 2298      public readonly Expression[] Exprs;
 2299      public XConstraintWithExprs(IToken tok, string constraintName, Type[] types, Expression[] exprs, TypeConstraint.Er
 69902300        : base(tok, constraintName, types, errMsg) {
 2301        Contract.Requires(tok != null);
 2302        Contract.Requires(constraintName != null);
 2303        Contract.Requires(types != null);
 2304        Contract.Requires(exprs != null);
 2305        Contract.Requires(errMsg != null);
 34952306        this.Exprs = exprs;
 34952307      }
 2308    }
 2309
 2310    public class XConstraint_EquatableArg : XConstraint {
 2311      public bool AllowSuperSub;
 2312      public bool TreatTypeParamAsWild;
 2313      public XConstraint_EquatableArg(IToken tok, Type a, Type b, bool allowSuperSub, bool treatTypeParamAsWild, TypeCon
 549062314        : base(tok, "EquatableArg", new Type[] { a, b }, errMsg) {
 2315        Contract.Requires(tok != null);
 2316        Contract.Requires(a != null);
 2317        Contract.Requires(b != null);
 2318        Contract.Requires(errMsg != null);
 274532319        AllowSuperSub = allowSuperSub;
 274532320        TreatTypeParamAsWild = treatTypeParamAsWild;
 274532321      }
 2322    }
 2323
 2324    /// <summary>
 2325    /// Solves or simplifies as many type constraints as possible.
 2326    /// If "allowDecisions" is "false", then no decisions, only determined inferences, are made; this mode is
 2327    /// appropriate for the partial solving that's done before a member lookup.
 2328    /// </summary>
 624072329    public void PartiallySolveTypeConstraints(bool allowDecisions) {
 624072330      int state = 0;
 8552662331      while (true) {
 4587242332        if (2 <= state && !allowDecisions) {
 2333          // time to say goodnight to Napoli
 310912334          return;
 4278582335        } else if (AllTypeConstraints.Count == 0 && AllXConstraints.Count == 0) {
 2336          // we're done
 313162337          return;
 2338        }
 2339
 3652262340        var anyNewConstraints = false;
 3652262341        var fullStrength = false;
 2342        // Process subtyping constraints
 3652262343        PrintTypeConstraintState(220 + 2 * state);
 3652262344        switch (state) {
 1749052345          case 0: {
 1749052346              var allTypeConstraints = AllTypeConstraints;
 1749052347              AllTypeConstraints = new List<TypeConstraint>();
 1749052348              var processed = new HashSet<TypeConstraint>();
 1440058862349              foreach (var c in allTypeConstraints) {
 478270572350                ProcessOneSubtypingConstraintAndItsSubs(c, processed, fullStrength, ref anyNewConstraints);
 478270572351              }
 2352
 1749052353              allTypeConstraints = new List<TypeConstraint>(AllTypeConstraints);  // copy the list
 1406078312354              foreach (var c in allTypeConstraints) {
 466943722355                var super = c.Super.NormalizeExpand() as TypeProxy;
 466947292356                if (AssignKnownEnd(super, true, fullStrength)) {
 3572357                  anyNewConstraints = true;
 466943722358                } else if (super != null && fullStrength && AssignKnownEndsFullstrength(super)) {  // KRML: is this used
 02359                  anyNewConstraints = true;
 02360                }
 466943722361              }
 1749052362            }
 1749052363            break;
 2364
 1277772365          case 1: {
 2366              // Process XConstraints
 2367              // confirm as many XConstraints as possible, setting "anyNewConstraints" to "true" if the confirmation
 2368              // of an XConstraint gives rise to new constraints to be handled in the loop above
 2369              bool generatedMoreXConstraints;
 1810742370              do {
 1810742371                generatedMoreXConstraints = false;
 1810742372                var allXConstraints = AllXConstraints;
 1810742373                AllXConstraints = new List<XConstraint>();
 487944872374                foreach (var xc in allXConstraints) {
 166308652375                  if (xc.Confirm(this, fullStrength, out var convertedIntoOtherTypeConstraints, out var moreXConstraints
 8700522376                    if (convertedIntoOtherTypeConstraints) {
 3229422377                      anyNewConstraints = true;
 5471102378                    } else {
 2241682379                      generatedMoreXConstraints = true;
 2241682380                    }
 5842352381                    if (moreXConstraints) {
 371252382                      generatedMoreXConstraints = true;
 371252383                    }
 160837552384                  } else {
 155366452385                    AllXConstraints.Add(xc);
 155366452386                  }
 160837552387                }
 3621482388              } while (generatedMoreXConstraints);
 1277772389            }
 1277772390            break;
 2391
 367682392          case 2: {
 52004652393              var assignables = AllXConstraints.Where(xc => xc.ConstraintName == "Assignable").ToList();
 367682394              var postponeForNow = new HashSet<TypeProxy>();
 402472892395              foreach (var constraint in AllTypeConstraints) {
 133789952396                var lhs = constraint.Super.NormalizeExpandKeepConstraints() as NonProxyType;
 162737412397                if (lhs != null) {
 106995872398                  foreach (var ta in lhs.TypeArgs) {
 6717832399                    AddAllProxies(ta, postponeForNow);
 6717832400                  }
 28947462401                }
 133789952402              }
 402472892403              foreach (var constraint in AllTypeConstraints) {
 133789952404                var lhs = constraint.Super.Normalize() as TypeProxy;
 166120272405                if (lhs != null && !postponeForNow.Contains(lhs)) {
 5712321072406                  var rhss = assignables.Where(xc => xc.Types[0].Normalize() == lhs).Select(xc => xc.Types[1]).ToList();
 32385602407                  if (ProcessAssignable(lhs, rhss)) {
 55282408                    anyNewConstraints = true;  // next time around the big loop, start with state 0 again
 55282409                  }
 32330322410                }
 133789952411              }
 36005912412              foreach (var assignable in assignables) {
 11719662413                var lhs = assignable.Types[0].Normalize() as TypeProxy;
 17228592414                if (lhs != null && !postponeForNow.Contains(lhs)) {
 909529042415                  var rhss = assignables.Where(xc => xc.Types[0].Normalize() == lhs).Select(xc => xc.Types[1]).ToList();
 5765042416                  if (ProcessAssignable(lhs, rhss)) {
 256112417                    anyNewConstraints = true;  // next time around the big loop, start with state 0 again
 2418                                               // process only one Assignable constraint in this way
 256112419                    break;
 2420                  }
 5252822421                }
 11463552422              }
 367682423            }
 367682424            break;
 2425
 2426          case 3:
 110632427            anyNewConstraints = ConvertAssignableToSubtypeConstraints(null);
 110632428            break;
 2429
 108692430          case 4: {
 108692431              var allTC = AllTypeConstraints;
 108692432              AllTypeConstraints = new List<TypeConstraint>();
 108692433              var proxyProcessed = new HashSet<TypeProxy>();
 16532372434              foreach (var c in allTC) {
 5402102435                ProcessFullStrength_SubDirection(c.Super, proxyProcessed, ref anyNewConstraints);
 5402102436              }
 4542602437              foreach (var xc in AllXConstraints) {
 2138042438                if (xc.ConstraintName == "Assignable") {
 732532439                  ProcessFullStrength_SubDirection(xc.Types[0], proxyProcessed, ref anyNewConstraints);
 732532440                }
 1405512441              }
 215572442              if (!anyNewConstraints) {
 2443                // only do super-direction if sub-direction had no effect
 106882444                proxyProcessed = new HashSet<TypeProxy>();
 14025812445                foreach (var c in allTC) {
 4568392446                  ProcessFullStrength_SuperDirection(c.Sub, proxyProcessed, ref anyNewConstraints);
 4568392447                }
 3759032448                foreach (var xc in AllXConstraints) {
 1749132449                  if (xc.ConstraintName == "Assignable") {
 603002450                    ProcessFullStrength_SuperDirection(xc.Types[1], proxyProcessed, ref anyNewConstraints);
 603002451                  }
 1146132452                }
 106882453              }
 108692454              AllTypeConstraints.AddRange(allTC);
 108692455            }
 108692456            break;
 2457
 28332458          case 5: {
 2459              // Process default numeric types
 28332460              var allTypeConstraints = AllTypeConstraints;
 28332461              AllTypeConstraints = new List<TypeConstraint>();
 1812122462              foreach (var c in allTypeConstraints) {
 1082402463                if (c.Super is ArtificialType) {
 506692464                  var proxy = c.Sub.NormalizeExpand() as TypeProxy;
 745972465                  if (proxy != null) {
 239282466                    AssignProxyAndHandleItsConstraints(proxy, c.Super is IntVarietiesSupertype ? (Type)Type.Int : Type.R
 239282467                    anyNewConstraints = true;
 239282468                    continue;
 2469                  }
 267412470                }
 336432471                AllTypeConstraints.Add(c);
 336432472              }
 28332473            }
 28332474            break;
 2475
 9862476          case 6: {
 9862477              fullStrength = true;
 2478              bool generatedMoreXConstraints;
 9862479              do {
 9862480                generatedMoreXConstraints = false;
 9862481                var allXConstraints = AllXConstraints;
 9862482                AllXConstraints = new List<XConstraint>();
 97682483                foreach (var xc in allXConstraints) {
 39182484                  if ((xc.ConstraintName == "Equatable" || xc.ConstraintName == "EquatableArg") && xc.Confirm(this, full
 32962485                    if (convertedIntoOtherTypeConstraints) {
 16482486                      anyNewConstraints = true;
 16482487                    } else {
 02488                      generatedMoreXConstraints = true;
 02489                    }
 16482490                    if (moreXConstraints) {
 02491                      generatedMoreXConstraints = true;
 02492                    }
 22702493                  } else {
 6222494                    AllXConstraints.Add(xc);
 6222495                  }
 22702496                }
 19722497              } while (generatedMoreXConstraints);
 9862498            }
 9862499            break;
 2500
 102501          case 7: {
 2502              // Process default reference types
 102503              var allXConstraints = AllXConstraints;
 102504              AllXConstraints = new List<XConstraint>();
 452505              foreach (var xc in allXConstraints) {
 52506                if (xc.ConstraintName == "IsRefType" || xc.ConstraintName == "IsNullableRefType") {
 02507                  var proxy = xc.Types[0].Normalize() as TypeProxy;  // before we started processing default types, this
 02508                  if (proxy != null) {
 02509                    AssignProxyAndHandleItsConstraints(proxy, builtIns.ObjectQ());
 02510                    anyNewConstraints = true;
 02511                    continue;
 2512                  }
 02513                }
 52514                AllXConstraints.Add(xc);
 52515              }
 102516            }
 102517            break;
 2518
 202519          case 8: fullStrength = true; goto case 0;
 202520          case 9: fullStrength = true; goto case 1;
 2521
 102522          case 10: {
 2523              // Finally, collapse constraints involving only proxies, which will have the effect of trading some type e
 2524              // messages for type-underspecification messages.
 102525              var allTypeConstraints = AllTypeConstraints;
 102526              AllTypeConstraints = new List<TypeConstraint>();
 1202527              foreach (var c in allTypeConstraints) {
 302528                var super = c.Super.NormalizeExpand();
 302529                var sub = c.Sub.NormalizeExpand();
 402530                if (super == sub) {
 102531                  continue;
 402532                } else if (super is TypeProxy && sub is TypeProxy) {
 202533                  var proxy = (TypeProxy)super;
 202534                  if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02535                    Options.OutputWriter.WriteLine("DEBUG: (merge in PartiallySolve) assigning proxy {0}.T := {1}", prox
 02536                  }
 202537                  proxy.T = sub;
 202538                  anyNewConstraints = true;  // signal a change in the constraints
 202539                  continue;
 2540                }
 02541                AllTypeConstraints.Add(c);
 02542              }
 102543            }
 102544            break;
 2545
 52546          case 11: {
 2547              // Last resort decisions. Sometimes get here even with some 'obvious'
 2548              // inferences. Before this case was added, the type inference returned with
 2549              // failure, so this is a conservative addition, and could be made more
 2550              // capable.
 52551              if (!allowDecisions) {
 02552                break;
 2553              }
 2554
 252555              foreach (var c in AllXConstraints) {
 102556                if (c.ConstraintName == "EquatableArg") {
 52557                  ConstrainSubtypeRelation_Equal(c.Types[0], c.Types[1], c.errorMsg);
 52558                  anyNewConstraints = true;
 52559                  AllXConstraints.Remove(c);
 52560                  break;
 2561                }
 02562              }
 102563              if (anyNewConstraints) {
 52564                break;
 2565              }
 2566
 02567              TypeConstraint.ErrorMsg oneSuperErrorMsg = null;
 02568              TypeConstraint.ErrorMsg oneSubErrorMsg = null;
 02569              var ss = new HashSet<Type>();
 02570              foreach (var c in AllTypeConstraints) {
 02571                var super = c.Super.NormalizeExpand();
 02572                var sub = c.Sub.NormalizeExpand();
 02573                if (super is TypeProxy && !ss.Contains(super)) {
 02574                  ss.Add(super);
 02575                }
 02576                if (sub is TypeProxy && !ss.Contains(sub)) {
 02577                  ss.Add(sub);
 02578                }
 02579              }
 2580
 02581              foreach (var t in ss) {
 02582                var lowers = new HashSet<Type>();
 02583                var uppers = new HashSet<Type>();
 02584                foreach (var c in AllTypeConstraints) {
 02585                  var super = c.Super.NormalizeExpand();
 02586                  var sub = c.Sub.NormalizeExpand();
 02587                  if (t.Equals(super)) {
 02588                    lowers.Add(sub);
 02589                    oneSubErrorMsg = c.ErrMsg;
 02590                  }
 02591                  if (t.Equals(sub)) {
 02592                    uppers.Add(super);
 02593                    oneSuperErrorMsg = c.ErrMsg;
 02594                  }
 02595                }
 2596
 02597                bool done = false;
 02598                foreach (var tl in lowers) {
 02599                  foreach (var tu in uppers) {
 02600                    if (tl.Equals(tu)) {
 02601                      if (!ContainsAsTypeParameter(tu, t)) {
 02602                        var errorMsg = new TypeConstraint.ErrorMsgWithBase(AllTypeConstraints[0].ErrMsg,
 02603                          "Decision: {0} is decided to be {1} because the latter is both the upper and lower bound to th
 02604                          t, tu);
 02605                        ConstrainSubtypeRelation_Equal(t, tu, errorMsg);
 2606                        // The above changes t so that it is a proxy with an assigned type
 02607                        anyNewConstraints = true;
 02608                        done = true;
 02609                        break;
 2610                      }
 02611                    }
 02612                  }
 02613                  if (done) {
 02614                    break;
 2615                  }
 02616                }
 02617              }
 02618              if (anyNewConstraints) {
 02619                break;
 2620              }
 2621
 02622              foreach (var t in ss) {
 02623                var lowers = new HashSet<Type>();
 02624                var uppers = new HashSet<Type>();
 02625                foreach (var c in AllTypeConstraints) {
 02626                  var super = c.Super.NormalizeExpand();
 02627                  var sub = c.Sub.NormalizeExpand();
 02628                  if (t.Equals(super)) {
 02629                    lowers.Add(sub);
 02630                  }
 2631
 02632                  if (t.Equals(sub)) {
 02633                    uppers.Add(super);
 02634                  }
 02635                }
 2636
 02637                if (uppers.Count == 0) {
 02638                  if (lowers.Count == 1) {
 02639                    var em = lowers.GetEnumerator();
 02640                    em.MoveNext();
 02641                    if (!ContainsAsTypeParameter(em.Current, t)) {
 02642                      var errorMsg = new TypeConstraint.ErrorMsgWithBase(oneSubErrorMsg,
 02643                        "Decision: {0} is decided to be {1} because the latter is a lower bound to the proxy and there i
 02644                        t, em.Current);
 02645                      ConstrainSubtypeRelation_Equal(t, em.Current, errorMsg);
 02646                      anyNewConstraints = true;
 02647                      break;
 2648                    }
 02649                  }
 02650                }
 02651                if (lowers.Count == 0) {
 02652                  if (uppers.Count == 1) {
 02653                    var em = uppers.GetEnumerator();
 02654                    em.MoveNext();
 02655                    if (!ContainsAsTypeParameter(em.Current, t)) {
 02656                      var errorMsg = new TypeConstraint.ErrorMsgWithBase(oneSuperErrorMsg,
 02657                        "Decision: {0} is decided to be {1} because the latter is an upper bound to the proxy and there 
 02658                        t, em.Current);
 02659                      ConstrainSubtypeRelation_Equal(t, em.Current, errorMsg);
 02660                      anyNewConstraints = true;
 02661                      break;
 2662                    }
 02663                  }
 02664                }
 02665              }
 2666
 02667              break;
 2668            }
 2669
 2670          case 12:
 2671            // we're so out of here
 02672            return;
 2673        }
 5024692674        if (anyNewConstraints) {
 1372432675          state = 0;
 3652262676        } else {
 2279832677          state++;
 2279832678        }
 3652262679      }
 624072680    }
 2681
 31622682    TypeProxy NewIntegerBasedProxy(IToken tok) {
 2683      Contract.Requires(tok != null);
 31622684      var proxy = new InferredTypeProxy();
 31622685      ConstrainSubtypeRelation(new IntVarietiesSupertype(), proxy, tok, "integer literal used as if it had type {0}", pr
 31622686      return proxy;
 31622687    }
 2688
 02689    private bool ContainsAsTypeParameter(Type t, Type u) {
 02690      if (t.Equals(u)) {
 02691        return true;
 2692      }
 2693
 02694      if (t is UserDefinedType udt) {
 02695        foreach (var tp in udt.TypeArgs) {
 02696          if (ContainsAsTypeParameter(tp, u)) {
 02697            return true;
 2698          }
 02699        }
 02700      }
 02701      if (t is CollectionType st) {
 02702        foreach (var tp in st.TypeArgs) {
 02703          if (ContainsAsTypeParameter(tp, u)) {
 02704            return true;
 2705          }
 02706        }
 02707      }
 02708      return false;
 02709    }
 2710
 6839882711    private void AddAllProxies(Type type, HashSet<TypeProxy> proxies) {
 2712      Contract.Requires(type != null);
 2713      Contract.Requires(proxies != null);
 6839882714      var proxy = type as TypeProxy;
 7217772715      if (proxy != null) {
 377892716        proxies.Add(proxy);
 6839882717      } else {
 19752122718        foreach (var ta in type.TypeArgs) {
 122052719          AddAllProxies(ta, proxies);
 122052720        }
 6461992721      }
 6839882722    }
 2723
 2724    /// <summary>
 2725    /// Set "lhs" to the join of "rhss" and "lhs.Subtypes, if possible.
 2726    /// Returns "true' if something was done, or "false" otherwise.
 2727    /// </summary>
 37839252728    private bool ProcessAssignable(TypeProxy lhs, List<Type> rhss) {
 2729      Contract.Requires(lhs != null && lhs.T == null);
 2730      Contract.Requires(rhss != null);
 37839252731      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02732        Console.Write("DEBUG: ProcessAssignable: {0} with rhss:", lhs);
 02733        foreach (var rhs in rhss) {
 02734          Options.OutputWriter.Write(" {0}", rhs);
 02735        }
 02736        Options.OutputWriter.Write(" subtypes:");
 02737        foreach (var sub in lhs.SubtypesKeepConstraints) {
 02738          Options.OutputWriter.Write(" {0}", sub);
 02739        }
 02740        Options.OutputWriter.WriteLine();
 02741      }
 37839252742      Type join = null;
 126538692743      foreach (var rhs in rhss) {
 16351942744        if (rhs is TypeProxy) { return false; }
 908422745        join = join == null ? rhs : Type.Join(join, rhs, builtIns);
 908422746      }
 163641762747      foreach (var sub in lhs.SubtypesKeepConstraints) {
 96278702748        if (sub is TypeProxy) { return false; }
 592172749        join = join == null ? sub : Type.Join(join, sub, builtIns);
 592172750      }
 1280412751      if (join == null) {
 484512752        return false;
 311392753      } else if (Reaches(join, lhs, 1, new HashSet<TypeProxy>())) {
 2754        // would cause a cycle, so don't do it
 02755        return false;
 311392756      } else {
 311392757        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02758          Options.OutputWriter.WriteLine("DEBUG: ProcessAssignable: assigning proxy {0}.T := {1}", lhs, join);
 02759        }
 311392760        lhs.T = join;
 311392761        return true;
 2762      }
 37839252763    }
 2764
 2765    /// <summary>
 2766    /// Convert each Assignable(A, B) constraint into a subtyping constraint A :> B,
 2767    /// provided that:
 2768    ///  - B is a non-proxy, and
 2769    ///  - either "proxySpecialization" is null or some proxy in "proxySpecializations" prominently appears in A.
 2770    /// </summary>
 259252771    bool ConvertAssignableToSubtypeConstraints(ISet<TypeProxy>/*?*/ proxySpecializations) {
 259252772      var anyNewConstraints = false;
 2773      // If (the head of) the RHS of an Assignable is known, convert the XConstraint into a subtyping constraint
 259252774      var allX = AllXConstraints;
 259252775      AllXConstraints = new List<XConstraint>();
 23146082776      foreach (var xc in allX) {
 8850592777        if (xc.ConstraintName == "Assignable" && xc.Types[1].Normalize() is NonProxyType) {
 1394482778          var t0 = xc.Types[0].NormalizeExpand();
 1394482779          if (proxySpecializations == null
 1394482780            || proxySpecializations.Contains(t0)
 1400302781            || t0.TypeArgs.Exists(ta => proxySpecializations.Contains(ta))) {
 5822782            ConstrainSubtypeRelation(t0, xc.Types[1], xc.errorMsg, true);
 5822783            anyNewConstraints = true;
 5822784            continue;
 2785          }
 1388662786        }
 7450292787        AllXConstraints.Add(xc);
 7450292788      }
 259252789      return anyNewConstraints;
 259252790    }
 2791
 148622792    bool TightenUpEquatable(ISet<TypeProxy> proxiesOfInterest) {
 2793      Contract.Requires(proxiesOfInterest != null);
 148622794      var anyNewConstraints = false;
 148622795      var allX = AllXConstraints;
 148622796      AllXConstraints = new List<XConstraint>();
 17790422797      foreach (var xc in allX) {
 5825602798        if (xc.ConstraintName == "Equatable" || xc.ConstraintName == "EquatableArg") {
 44082799          var t0 = xc.Types[0].NormalizeExpandKeepConstraints();
 44082800          var t1 = xc.Types[1].NormalizeExpandKeepConstraints();
 44082801          if (proxiesOfInterest.Contains(t0) || proxiesOfInterest.Contains(t1)) {
 02802            ConstrainSubtypeRelation_Equal(t0, t1, xc.errorMsg);
 02803            anyNewConstraints = true;
 02804            continue;
 2805          }
 44082806        }
 5781522807        AllXConstraints.Add(xc);
 5781522808      }
 148622809      return anyNewConstraints;
 148622810    }
 2811
 608826162812    void ProcessOneSubtypingConstraintAndItsSubs(TypeConstraint c, ISet<TypeConstraint> processed, bool fullStrength, re
 2813      Contract.Requires(c != null);
 2814      Contract.Requires(processed != null);
 739589222815      if (processed.Contains(c)) {
 130763062816        return;  // our job has already been done, or is at least in progress
 2817      }
 478063102818      processed.Add(c);
 2819
 478063102820      var super = c.Super.NormalizeExpandKeepConstraints();
 478063102821      var sub = c.Sub.NormalizeExpandKeepConstraints();
 2822      // Process all subtype types before going on
 478063102823      var subProxy = sub as TypeProxy;
 941027162824      if (subProxy != null) {
 1780558952825        foreach (var cc in subProxy.SubtypeConstraints) {
 130555592826          ProcessOneSubtypingConstraintAndItsSubs(cc, processed, fullStrength, ref anyNewConstraints);
 130555592827        }
 462964062828      }
 2829      // the processing may have assigned some proxies, so we'll refresh super and sub
 478063102830      super = super.NormalizeExpandKeepConstraints();
 478063102831      sub = sub.NormalizeExpandKeepConstraints();
 2832
 487765922833      if (super.Equals(sub)) {
 2834        // the constraint is satisfied, so just drop it
 480834402835      } else if ((super is NonProxyType || super is ArtificialType) && sub is NonProxyType) {
 2771302836        ImposeSubtypingConstraint(super, sub, c.ErrMsg);
 2771302837        anyNewConstraints = true;
 468360482838      } else if (AssignKnownEnd(sub as TypeProxy, true, fullStrength)) {
 202839        anyNewConstraints = true;
 465588982840      } else if (sub is TypeProxy && fullStrength && AssignKnownEndsFullstrength((TypeProxy)sub)) {
 02841        anyNewConstraints = true;
 465588782842      } else {
 2843        // keep the constraint for now
 465588782844        AllTypeConstraints.Add(c);
 465588782845      }
 608826162846    }
 2847
 7571642848    void ProcessFullStrength_SubDirection(Type t, ISet<TypeProxy> processed, ref bool anyNewConstraints) {
 2849      Contract.Requires(t != null);
 2850      Contract.Requires(processed != null);
 7571642851      var proxy = t.NormalizeExpand() as TypeProxy;
 10453832852      if (proxy != null) {
 3912262853        if (processed.Contains(proxy)) {
 1030072854          return;  // our job has already been done, or is at least in progress
 2855        }
 1852122856        processed.Add(proxy);
 2857
 9867392858        foreach (var u in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 1437012859          ProcessFullStrength_SubDirection(u, processed, ref anyNewConstraints);
 1437012860        }
 1852122861        proxy = proxy.NormalizeExpand() as TypeProxy;
 1856452862        if (proxy != null && AssignKnownEndsFullstrength_SubDirection(proxy)) {
 4332863          anyNewConstraints = true;
 4332864        }
 1852122865      }
 7571642866    }
 2867
 8697122868    void ProcessFullStrength_SuperDirection(Type t, ISet<TypeProxy> processed, ref bool anyNewConstraints) {
 2869      Contract.Requires(t != null);
 2870      Contract.Requires(processed != null);
 8697122871      var proxy = t.NormalizeExpand() as TypeProxy;
 11990702872      if (proxy != null) {
 4284832873        if (processed.Contains(proxy)) {
 991252874          return;  // our job has already been done, or is at least in progress
 2875        }
 2302332876        processed.Add(proxy);
 2877
 17484182878        foreach (var u in proxy.Supertypes) {
 3525732879          ProcessFullStrength_SuperDirection(u, processed, ref anyNewConstraints);
 3525732880        }
 2302332881        proxy = proxy.NormalizeExpand() as TypeProxy;
 3487182882        if (proxy != null && AssignKnownEndsFullstrength_SuperDirection(proxy)) {
 1184852883          anyNewConstraints = true;
 1184852884        }
 2302332885      }
 8697122886    }
 2887
 2888    /// <summary>
 2889    /// Returns true if anything happened.
 2890    /// </summary>
 937496382891    bool AssignKnownEnd(TypeProxy proxy, bool keepConstraints, bool fullStrength) {
 2892      Contract.Requires(proxy == null || proxy.T == null);  // caller is supposed to have called NormalizeExpand
 1282707302893      if (proxy == null) {
 2894        // nothing to do
 345210922895        return false;
 2896      }
 2897      // ----- first, go light; also, prefer subtypes over supertypes
 592285462898      IEnumerable<Type> subTypes = keepConstraints ? proxy.SubtypesKeepConstraints : proxy.Subtypes;
 3374206242899      foreach (var su in subTypes) {
 533020462900        DetermineRootLeaf(su, out var isRoot, out _, out var headRoot, out _);
 533020462901        Contract.Assert(!isRoot || headRoot);  // isRoot ==> headRoot
 534579032902        if (isRoot) {
 1558572903          if (Reaches(su, proxy, 1, new HashSet<TypeProxy>())) {
 2904            // adding a constraint here would cause a bad cycle, so we don't
 1558572905          } else {
 1558572906            AssignProxyAndHandleItsConstraints(proxy, su, keepConstraints);
 1558572907            return true;
 2908          }
 531614842909        } else if (headRoot) {
 152952910          if (Reaches(su, proxy, 1, new HashSet<TypeProxy>())) {
 2911            // adding a constraint here would cause a bad cycle, so we don't
 152952912          } else {
 152952913            AssignProxyAndHandleItsConstraints(proxy, TypeProxy.HeadWithProxyArgs(su), keepConstraints);
 152952914            return true;
 2915          }
 02916        }
 531308942917      }
 590574542918      if (fullStrength) {
 602919        IEnumerable<Type> superTypes = keepConstraints ? proxy.SupertypesKeepConstraints : proxy.Supertypes;
 3752920        foreach (var su in superTypes) {
 652921          DetermineRootLeaf(su, out _, out var isLeaf, out _, out var headLeaf);
 652922          Contract.Assert(!isLeaf || headLeaf);  // isLeaf ==> headLeaf
 652923          if (isLeaf) {
 02924            if (Reaches(su, proxy, -1, new HashSet<TypeProxy>())) {
 2925              // adding a constraint here would cause a bad cycle, so we don't
 02926            } else {
 02927              AssignProxyAndHandleItsConstraints(proxy, su, keepConstraints);
 02928              return true;
 2929            }
 652930          } else if (headLeaf) {
 02931            if (Reaches(su, proxy, -1, new HashSet<TypeProxy>())) {
 2932              // adding a constraint here would cause a bad cycle, so we don't
 02933            } else {
 02934              AssignProxyAndHandleItsConstraints(proxy, TypeProxy.HeadWithProxyArgs(su), keepConstraints);
 02935              return true;
 2936            }
 02937          }
 652938        }
 602939      }
 590573942940      return false;
 937496382941    }
 2942
 602943    bool AssignKnownEndsFullstrength(TypeProxy proxy) {
 2944      Contract.Requires(proxy != null);
 2945      // ----- continue with full strength
 2946      // If the join of the subtypes exists, use it
 602947      var joins = new List<Type>();
 4952948      foreach (var su in proxy.Subtypes) {
 2102949        if (su is TypeProxy) {
 1052950          continue;  // don't include proxies in the meet computation
 2951        }
 02952        int i = 0;
 02953        for (; i < joins.Count; i++) {
 02954          var j = Type.Join(joins[i], su, builtIns);
 02955          if (j != null) {
 02956            joins[i] = j;
 02957            break;
 2958          }
 02959        }
 02960        if (i == joins.Count) {
 2961          // we went to the end without finding a place to meet up
 02962          joins.Add(su);
 02963        }
 02964      }
 602965      if (joins.Count == 1 && !Reaches(joins[0], proxy, 1, new HashSet<TypeProxy>())) {
 2966        // we were able to compute a meet of all the subtyping constraints, so use it
 02967        AssignProxyAndHandleItsConstraints(proxy, joins[0]);
 02968        return true;
 2969      }
 2970      // If the meet of the supertypes exists, use it
 602971      var meets = new List<Type>();
 3752972      foreach (var su in proxy.Supertypes) {
 1302973        if (su is TypeProxy) {
 652974          continue;  // don't include proxies in the meet computation
 2975        }
 02976        int i = 0;
 02977        for (; i < meets.Count; i++) {
 02978          var j = Type.Meet(meets[i], su, builtIns);
 02979          if (j != null) {
 02980            meets[i] = j;
 02981            break;
 2982          }
 02983        }
 02984        if (i == meets.Count) {
 2985          // we went to the end without finding a place to meet
 02986          meets.Add(su);
 02987        }
 02988      }
 602989      if (meets.Count == 1 && !(meets[0] is ArtificialType) && !Reaches(meets[0], proxy, -1, new HashSet<TypeProxy>())) 
 2990        // we were able to compute a meet of all the subtyping constraints, so use it
 02991        AssignProxyAndHandleItsConstraints(proxy, meets[0]);
 02992        return true;
 2993      }
 2994
 602995      return false;
 602996    }
 2997
 1852122998    bool AssignKnownEndsFullstrength_SubDirection(TypeProxy proxy) {
 2999      Contract.Requires(proxy != null && proxy.T == null);
 3000      // If the join the subtypes exists, use it
 1852123001      var joins = new List<Type>();
 1852123002      var proxySubs = new HashSet<TypeProxy>();
 1852123003      proxySubs.Add(proxy);
 9867393004      foreach (var su in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 2863373005        if (su is TypeProxy) {
 1426363006          proxySubs.Add((TypeProxy)su);
 1437013007        } else {
 10653008          int i = 0;
 16973009          for (; i < joins.Count; i++) {
 6323010            var j = Type.Join(joins[i], su, builtIns);
 12643011            if (j != null) {
 6323012              joins[i] = j;
 6323013              break;
 3014            }
 03015          }
 14983016          if (i == joins.Count) {
 3017            // we went to the end without finding a place to join in
 4333018            joins.Add(su);
 4333019          }
 10653020        }
 1437013021      }
 1856453022      if (joins.Count == 1 && !Reaches(joins[0], proxy, 1, new HashSet<TypeProxy>())) {
 3023        // We were able to compute a join of all the subtyping constraints, so use it.
 3024        // Well, maybe.  If "join[0]" denotes a non-null type and "proxy" is something
 3025        // that could be assigned "null", then set "proxy" to the nullable version of "join[0]".
 3026        // Stated differently, think of an applicable "IsNullableRefType" constraint as
 3027        // being part of the join computation, essentially throwing in a "...?".
 3028        // Except: If the join is a tight bound--meaning, it is also a meet--then pick it
 3029        // after all, because that seems to give rise to less confusing error messages.
 8463030        if (joins[0].IsNonNullRefType) {
 4133031          Type meet = null;
 4133032          if (MeetOfAllSupertypes(proxy, ref meet, new HashSet<TypeProxy>(), false) && meet != null && Type.SameHead(joi
 3033            // leave it
 4133034          } else {
 4133035            CloseOverAssignableRhss(proxySubs);
 4133036            if (HasApplicableNullableRefTypeConstraint(proxySubs)) {
 03037              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 03038                Options.OutputWriter.WriteLine("DEBUG: Found join {0} for proxy {1}, but weakening it to {2}", joins[0],
 03039              }
 03040              AssignProxyAndHandleItsConstraints(proxy, joins[0].NormalizeExpand(), true);
 03041              return true;
 3042            }
 4133043          }
 4133044        }
 4333045        AssignProxyAndHandleItsConstraints(proxy, joins[0], true);
 4333046        return true;
 3047      }
 1847793048      return false;
 1852123049    }
 3050
 4133051    private void CloseOverAssignableRhss(ISet<TypeProxy> proxySet) {
 3052      Contract.Requires(proxySet != null);
 8263053      while (true) {
 4133054        var moreChanges = false;
 2270193055        foreach (var xc in AllXConstraints) {
 1145353056          if (xc.ConstraintName == "Assignable") {
 392753057            var source = xc.Types[0].Normalize() as TypeProxy;
 392753058            var sink = xc.Types[1].Normalize() as TypeProxy;
 392753059            if (source != null && sink != null && proxySet.Contains(source) && !proxySet.Contains(sink)) {
 03060              proxySet.Add(sink);
 03061              moreChanges = true;
 03062            }
 392753063          }
 752603064        }
 8263065        if (!moreChanges) {
 4133066          return;
 3067        }
 03068      }
 4133069    }
 4133070    private bool HasApplicableNullableRefTypeConstraint(ISet<TypeProxy> proxySet) {
 3071      Contract.Requires(proxySet != null);
 4133072      var nullableProxies = new HashSet<TypeProxy>();
 2270193073      foreach (var xc in AllXConstraints) {
 752603074        if (xc.ConstraintName == "IsNullableRefType") {
 03075          var npr = xc.Types[0].Normalize() as TypeProxy;
 03076          if (npr != null) {
 03077            nullableProxies.Add(npr);
 03078          }
 03079        }
 752603080      }
 4133081      return proxySet.Any(nullableProxies.Contains);
 4133082    }
 6663083    private bool HasApplicableNullableRefTypeConstraint_SubDirection(TypeProxy proxy) {
 3084      Contract.Requires(proxy != null);
 6663085      var nullableProxies = new HashSet<TypeProxy>();
 38343086      foreach (var xc in AllXConstraints) {
 12243087        if (xc.ConstraintName == "IsNullableRefType") {
 6123088          var npr = xc.Types[0].Normalize() as TypeProxy;
 12243089          if (npr != null) {
 6123090            nullableProxies.Add(npr);
 6123091          }
 6123092        }
 6123093      }
 6663094      return HasApplicableNullableRefTypeConstraint_SubDirection_aux(proxy, nullableProxies, new HashSet<TypeProxy>());
 6663095    }
 6663096    private bool HasApplicableNullableRefTypeConstraint_SubDirection_aux(TypeProxy proxy, ISet<TypeProxy> nullableProxie
 3097      Contract.Requires(proxy != null);
 3098      Contract.Requires(nullableProxies != null);
 3099      Contract.Requires(visitedProxies != null);
 3100
 6663101      if (visitedProxies.Contains(proxy)) {
 03102        return false;
 3103      }
 6663104      visitedProxies.Add(proxy);
 3105
 12783106      if (nullableProxies.Contains(proxy)) {
 6123107        return true;
 3108      }
 3109
 1623110      foreach (var sub in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 03111        var psub = sub as TypeProxy;
 03112        if (psub != null && HasApplicableNullableRefTypeConstraint_SubDirection_aux(psub, nullableProxies, visitedProxie
 03113          return true;
 3114        }
 03115      }
 543116      return false;
 6663117    }
 3118
 2073013119    bool AssignKnownEndsFullstrength_SuperDirection(TypeProxy proxy) {
 3120      Contract.Requires(proxy != null && proxy.T == null);
 3121      // First, compute the the join of the Assignable LHSs.  Then, compute
 3122      // the meet of that join and the supertypes.
 2073013123      var joins = new List<Type>();
 665772183124      foreach (var xc in AllXConstraints) {
 220454053125        if (xc.ConstraintName == "Assignable" && xc.Types[1].Normalize() == proxy) {
 603003126          var su = xc.Types[0].Normalize();
 782293127          if (su is TypeProxy) {
 179293128            continue; // don't include proxies in the join computation
 3129          }
 423713130          int i = 0;
 423713131          for (; i < joins.Count; i++) {
 03132            var j = Type.Join(joins[i], su, builtIns);
 03133            if (j != null) {
 03134              joins[i] = j;
 03135              break;
 3136            }
 03137          }
 847423138          if (i == joins.Count) {
 3139            // we went to the end without finding a place to join in
 423713140            joins.Add(su);
 423713141          }
 423713142        }
 219671763143      }
 3144      // If the meet of the supertypes exists, use it
 2073013145      var meets = new List<Type>(joins);
 15395193146      foreach (var su in proxy.SupertypesKeepConstraints) {
 3222823147        if (su is TypeProxy) {
 164103148          continue;  // don't include proxies in the meet computation
 3149        }
 2894623150        int i = 0;
 4175533151        for (; i < meets.Count; i++) {
 1280913152          var j = Type.Meet(meets[i], su, builtIns);
 2561823153          if (j != null) {
 1280913154            meets[i] = j;
 1280913155            break;
 3156          }
 03157        }
 4508333158        if (i == meets.Count) {
 3159          // we went to the end without finding a place to meet up
 1613713160          meets.Add(su);
 1613713161        }
 2894623162      }
 3257863163      if (meets.Count == 1 && !(meets[0] is ArtificialType) && !Reaches(meets[0], proxy, -1, new HashSet<TypeProxy>())) 
 3164        // we were able to compute a meet of all the subtyping constraints, so use it
 1184853165        AssignProxyAndHandleItsConstraints(proxy, meets[0], true);
 1184853166        return true;
 3167      }
 888163168      return false;
 2073013169    }
 3170
 3171    int _reaches_recursion;
 5009433172    private bool Reaches(Type t, TypeProxy proxy, int direction, HashSet<TypeProxy> visited) {
 5009433173      if (_reaches_recursion == 20) {
 03174        Contract.Assume(false);  // possible infinite recursion
 03175      }
 5009433176      _reaches_recursion++;
 5009433177      var b = Reaches_aux(t, proxy, direction, visited);
 5009433178      _reaches_recursion--;
 5009433179      return b;
 5009433180    }
 5009433181    private bool Reaches_aux(Type t, TypeProxy proxy, int direction, HashSet<TypeProxy> visited) {
 3182      Contract.Requires(t != null);
 3183      Contract.Requires(proxy != null);
 3184      Contract.Requires(visited != null);
 5009433185      t = t.NormalizeExpand();
 5009433186      var tproxy = t as TypeProxy;
 9259623187      if (tproxy == null) {
 4250193188        var polarities = Type.GetPolarities(t).ConvertAll(TypeParameter.Direction);
 4250193189        Contract.Assert(polarities != null);
 4250193190        Contract.Assert(polarities.Count <= t.TypeArgs.Count);
 11748423191        for (int i = 0; i < polarities.Count; i++) {
 1082683192          if (Reaches(t.TypeArgs[i], proxy, direction * polarities[i], visited)) {
 03193            return true;
 3194          }
 1082683195        }
 4250193196        return false;
 775903197      } else if (tproxy == proxy) {
 16663198        return true;
 767493199      } else if (visited.Contains(tproxy)) {
 24913200        return false;
 717673201      } else {
 717673202        visited.Add(tproxy);
 1279513203        if (0 <= direction && tproxy.Subtypes.Any(su => Reaches(su, proxy, direction, visited))) {
 03204          return true;
 3205        }
 721573206        if (direction <= 0 && tproxy.Supertypes.Any(su => Reaches(su, proxy, direction, visited))) {
 03207          return true;
 3208        }
 717673209        return false;
 3210      }
 5009433211    }
 3212
 3213    /// <summary>
 3214    /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
 3215    /// </summary>
 17213216    void ResolveClassMemberBodiesInitial(TopLevelDeclWithMembers cl) {
 3217      Contract.Requires(cl != null);
 3218      Contract.Requires(currentClass == null);
 3219      Contract.Requires(AllTypeConstraints.Count == 0);
 3220      Contract.Ensures(currentClass == null);
 3221      Contract.Ensures(AllTypeConstraints.Count == 0);
 3222
 17213223      currentClass = cl;
 217743224      foreach (MemberDecl member in cl.Members) {
 55373225        Contract.Assert(VisibleInScope(member));
 55373226        if (member is ConstantField { Rhs: { } } constantField) {
 03227          var resolutionContext = new ResolutionContext(constantField, false);
 03228          scope.PushMarker();
 03229          if (constantField.IsStatic || currentClass == null || !currentClass.AcceptThis) {
 03230            scope.AllowInstance = false;
 03231          }
 03232          ResolveExpression(constantField.Rhs, resolutionContext);
 03233          scope.PopMarker();
 03234          AddAssignableConstraint(constantField.tok, constantField.Type, constantField.Rhs.Type,
 03235            "type for constant '" + constantField.Name + "' is '{0}', but its initialization value type is '{1}'");
 03236          SolveAllTypeConstraints();
 03237        }
 55373238      }
 17213239      currentClass = null;
 17213240    }
 3241
 3242    /// <summary>
 3243    /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
 3244    /// </summary>
 17213245    void ResolveClassMemberBodies(TopLevelDeclWithMembers cl) {
 3246      Contract.Requires(cl != null);
 3247      Contract.Requires(currentClass == null);
 3248      Contract.Requires(AllTypeConstraints.Count == 0);
 3249      Contract.Ensures(currentClass == null);
 3250      Contract.Ensures(AllTypeConstraints.Count == 0);
 3251
 17213252      currentClass = cl;
 217743253      foreach (MemberDecl member in cl.Members) {
 55373254        Contract.Assert(VisibleInScope(member));
 58433255        if (member is Field) {
 3063256          var resolutionContext = new ResolutionContext(new NoContext(currentClass.EnclosingModuleDefinition), false);
 3063257          scope.PushMarker();
 3063258          if (member.IsStatic) {
 03259            scope.AllowInstance = false;
 03260          }
 3063261          ResolveAttributes(member, resolutionContext, true);
 3063262          scope.PopMarker();
 3263
 55373264        } else if (member is Function function) {
 03265          var ec = reporter.Count(ErrorLevel.Error);
 03266          allTypeParameters.PushMarker();
 03267          ResolveTypeParameters(function.TypeArgs, false, function);
 3268
 03269          function.Resolve(this);
 03270          allTypeParameters.PopMarker();
 03271          if (function is ExtremePredicate { PrefixPredicate: { } prefixPredicate } && ec == reporter.Count(ErrorLevel.E
 03272            allTypeParameters.PushMarker();
 03273            ResolveTypeParameters(prefixPredicate.TypeArgs, false, prefixPredicate);
 03274            prefixPredicate.Resolve(this);
 03275            allTypeParameters.PopMarker();
 03276          }
 3277
 104623278        } else if (member is Method method) {
 52313279          var ec = reporter.Count(ErrorLevel.Error);
 52313280          allTypeParameters.PushMarker();
 52313281          ResolveTypeParameters(method.TypeArgs, false, method);
 52313282          method.Resolve(this);
 52313283          allTypeParameters.PopMarker();
 52313284          if (method is ExtremeLemma { PrefixLemma: { } prefixLemma } && ec == reporter.Count(ErrorLevel.Error)) {
 03285            allTypeParameters.PushMarker();
 03286            ResolveTypeParameters(prefixLemma.TypeArgs, false, prefixLemma);
 03287            prefixLemma.Resolve(this);
 03288            allTypeParameters.PopMarker();
 03289          }
 3290
 52313291        } else {
 03292          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected member type
 3293        }
 55373294        Contract.Assert(AllTypeConstraints.Count == 0);
 55373295      }
 17213296      currentClass = null;
 17213297    }
 3298
 3299    /// <summary>
 3300    /// Assumes type parameters have already been pushed
 3301    /// </summary>
 5273302    void ResolveCtorTypes(DatatypeDecl/*!*/ dt, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies, Graph<CoDatatypeDecl/*!*/
 3303      Contract.Requires(dt != null);
 3304      Contract.Requires(dependencies != null);
 3305      Contract.Requires(coDependencies != null);
 46173306      foreach (DatatypeCtor ctor in dt.Ctors) {
 3307
 10123308        ctor.EnclosingDatatype = dt;
 3309
 10123310        allTypeParameters.PushMarker();
 10123311        ResolveCtorSignature(ctor, dt.TypeArgs);
 10123312        allTypeParameters.PopMarker();
 3313
 20243314        if (dt is IndDatatypeDecl) {
 3315          // The dependencies of interest among inductive datatypes are all (inductive data)types mentioned in the param
 10123316          var idt = (IndDatatypeDecl)dt;
 10123317          dependencies.AddVertex(idt);
 54963318          foreach (Formal p in ctor.Formals) {
 8203319            AddDatatypeDependencyEdge(idt, p.Type, dependencies);
 8203320          }
 10123321        } else {
 3322          // The dependencies of interest among codatatypes are just the top-level types of parameters.
 03323          var codt = (CoDatatypeDecl)dt;
 03324          coDependencies.AddVertex(codt);
 03325          foreach (var p in ctor.Formals) {
 03326            var co = p.Type.AsCoDatatype;
 03327            if (co != null && codt.EnclosingModuleDefinition == co.EnclosingModuleDefinition) {
 03328              coDependencies.AddEdge(codt, co);
 03329            }
 03330          }
 03331        }
 10123332      }
 5273333    }
 3334
 10123335    void ResolveCtorSignature(DatatypeCtor ctor, List<TypeParameter> dtTypeArguments) {
 3336      Contract.Requires(ctor != null);
 3337      Contract.Requires(ctor.EnclosingDatatype != null);
 3338      Contract.Requires(dtTypeArguments != null);
 54963339      foreach (Formal p in ctor.Formals) {
 8203340        ResolveType(p.tok, p.Type, ctor.EnclosingDatatype, ResolveTypeOptionEnum.AllowPrefix, dtTypeArguments);
 8203341      }
 10123342    }
 3343
 8403344    void AddDatatypeDependencyEdge(IndDatatypeDecl dt, Type tp, Graph<IndDatatypeDecl> dependencies) {
 3345      Contract.Requires(dt != null);
 3346      Contract.Requires(tp != null);
 3347      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 3348
 8403349      tp = tp.NormalizeExpand();
 8403350      var dependee = tp.AsIndDatatype;
 8503351      if (dependee != null && dt.EnclosingModuleDefinition == dependee.EnclosingModuleDefinition) {
 103352        dependencies.AddEdge(dt, dependee);
 903353        foreach (var ta in ((UserDefinedType)tp).TypeArgs) {
 203354          AddDatatypeDependencyEdge(dt, ta, dependencies);
 203355        }
 103356      }
 8403357    }
 3358
 103359    public void ResolveFrameExpressionTopLevel(FrameExpression fe, FrameExpressionUse use, ICodeContext codeContext) {
 103360      ResolveFrameExpression(fe, use, new ResolutionContext(codeContext, false));
 103361    }
 3362
 103363    void ResolveFrameExpression(FrameExpression fe, FrameExpressionUse use, ResolutionContext resolutionContext) {
 3364      Contract.Requires(fe != null);
 3365      Contract.Requires(resolutionContext != null);
 3366
 103367      ResolveExpression(fe.E, resolutionContext);
 103368      Type t = fe.E.Type;
 103369      Contract.Assert(t != null);  // follows from postcondition of ResolveExpression
 103370      var eventualRefType = new InferredTypeProxy();
 103371      if (use == FrameExpressionUse.Reads) {
 03372        AddXConstraint(fe.E.tok, "ReadsFrame", t, eventualRefType,
 03373          "a reads-clause expression must denote an object, a set/iset/multiset/seq of objects, or a function to a set/i
 103374      } else {
 103375        AddXConstraint(fe.E.tok, "ModifiesFrame", t, eventualRefType,
 103376          use == FrameExpressionUse.Modifies ?
 103377          "a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got {0})" :
 103378          "an unchanged expression must denote an object or a set/iset/multiset/seq of objects (instead got {0})");
 103379      }
 103380      if (fe.FieldName != null) {
 03381        var member = ResolveMember(fe.E.tok, eventualRefType, fe.FieldName, out var tentativeReceiverType);
 03382        var ctype = (UserDefinedType)tentativeReceiverType;  // correctness of cast follows from the DenotesClass test a
 03383        if (member == null) {
 3384          // error has already been reported by ResolveMember
 03385        } else if (!(member is Field)) {
 03386          reporter.Error(MessageSource.Resolver, fe.E, "member {0} in type {1} does not refer to a field", fe.FieldName,
 03387        } else if (member is ConstantField) {
 03388          reporter.Error(MessageSource.Resolver, fe.E, "expression is not allowed to refer to constant field {0}", fe.Fi
 03389        } else {
 03390          Contract.Assert(ctype != null && ctype.ResolvedClass != null);  // follows from postcondition of ResolveMember
 03391          fe.Field = (Field)member;
 03392        }
 03393      }
 103394    }
 3395
 03396    void ResolveIterator(IteratorDecl iter) {
 3397      Contract.Requires(iter != null);
 3398      Contract.Requires(currentClass == null);
 3399      Contract.Ensures(currentClass == null);
 3400
 03401      var initialErrorCount = reporter.Count(ErrorLevel.Error);
 3402
 3403      // Add in-parameters to the scope, but don't care about any duplication errors, since they have already been repor
 03404      scope.PushMarker();
 03405      scope.AllowInstance = false;  // disallow 'this' from use, which means that the special fields and methods added a
 03406      iter.Ins.ForEach(p => scope.Push(p.Name, p));
 03407      ResolveParameterDefaultValues(iter.Ins, new ResolutionContext(iter, false));
 3408
 3409      // Start resolving specification...
 3410      // we start with the decreases clause, because the _decreases<n> fields were only given type proxies before; we'll
 3411      // the types only after resolving the decreases clause (and it may be that some of resolution has already seen use
 3412      // these fields; so, with no further ado, here we go
 03413      ResolveAttributes(iter.Decreases, new ResolutionContext(iter, false));
 03414      Contract.Assert(iter.Decreases.Expressions.Count == iter.DecreasesFields.Count);
 03415      for (var i = 0; i < iter.Decreases.Expressions.Count; i++) {
 03416        var e = iter.Decreases.Expressions[i];
 03417        ResolveExpression(e, new ResolutionContext(iter, false));
 3418        // any type is fine, but associate this type with the corresponding _decreases<n> field
 03419        var d = iter.DecreasesFields[i];
 3420        // If the following type constraint does not hold, then: Bummer, there was a use--and a bad use--of the field be
 03421        ConstrainSubtypeRelation(d.Type, e.Type, e, "type of field {0} is {1}, but has been constrained elsewhere to be 
 03422      }
 03423      foreach (FrameExpression fe in iter.Reads.Expressions) {
 03424        ResolveFrameExpressionTopLevel(fe, FrameExpressionUse.Reads, iter);
 03425      }
 03426      ResolveAttributes(iter.Modifies, new ResolutionContext(iter, false));
 03427      foreach (FrameExpression fe in iter.Modifies.Expressions) {
 03428        ResolveFrameExpressionTopLevel(fe, FrameExpressionUse.Modifies, iter);
 03429      }
 03430      foreach (AttributedExpression e in iter.Requires) {
 03431        ResolveAttributes(e, new ResolutionContext(iter, false));
 03432        ResolveExpression(e.E, new ResolutionContext(iter, false));
 03433        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03434        ConstrainTypeExprBool(e.E, "Precondition must be a boolean (got {0})");
 03435      }
 3436
 03437      scope.PopMarker();  // for the in-parameters
 3438
 3439      // We resolve the rest of the specification in an instance context.  So mentions of the in- or yield-parameters
 3440      // get resolved as field dereferences (with an implicit "this")
 03441      scope.PushMarker();
 03442      currentClass = iter;
 03443      Contract.Assert(scope.AllowInstance);
 3444
 03445      foreach (AttributedExpression e in iter.YieldRequires) {
 03446        ResolveAttributes(e, new ResolutionContext(iter, false));
 03447        ResolveExpression(e.E, new ResolutionContext(iter, false));
 03448        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03449        ConstrainTypeExprBool(e.E, "Yield precondition must be a boolean (got {0})");
 03450      }
 03451      foreach (AttributedExpression e in iter.YieldEnsures) {
 03452        ResolveAttributes(e, new ResolutionContext(iter, true));
 03453        ResolveExpression(e.E, new ResolutionContext(iter, true));
 03454        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03455        ConstrainTypeExprBool(e.E, "Yield postcondition must be a boolean (got {0})");
 03456      }
 03457      foreach (AttributedExpression e in iter.Ensures) {
 03458        ResolveAttributes(e, new ResolutionContext(iter, true));
 03459        ResolveExpression(e.E, new ResolutionContext(iter, true));
 03460        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03461        ConstrainTypeExprBool(e.E, "Postcondition must be a boolean (got {0})");
 03462      }
 03463      SolveAllTypeConstraints();
 3464
 03465      var postSpecErrorCount = reporter.Count(ErrorLevel.Error);
 3466
 3467      // Resolve body
 03468      if (iter.Body != null) {
 03469        DominatingStatementLabels.PushMarker();
 03470        foreach (var req in iter.Requires) {
 03471          if (req.Label != null) {
 03472            if (DominatingStatementLabels.Find(req.Label.Name) != null) {
 03473              reporter.Error(MessageSource.Resolver, req.Label.Tok, "assert label shadows a dominating label");
 03474            } else {
 03475              var rr = DominatingStatementLabels.Push(req.Label.Name, req.Label);
 03476              Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expec
 03477            }
 03478          }
 03479        }
 03480        ResolveBlockStatement(iter.Body, ResolutionContext.FromCodeContext(iter));
 03481        DominatingStatementLabels.PopMarker();
 03482        SolveAllTypeConstraints();
 03483      }
 3484
 03485      currentClass = null;
 03486      scope.PopMarker();  // pop off the AllowInstance setting
 3487
 03488      if (postSpecErrorCount == initialErrorCount) {
 03489        iter.CreateIteratorMethodSpecs(this);
 03490      }
 03491    }
 3492
 3493    /// <summary>
 3494    /// Checks if lhs, which is expected to be a successfully resolved expression, denotes something
 3495    /// that can be assigned to.  In particular, this means that lhs denotes a mutable variable, field,
 3496    /// or array element.  If a violation is detected, an error is reported.
 3497    /// </summary>
 1218233498    public void CheckIsLvalue(Expression lhs, ResolutionContext resolutionContext) {
 3499      Contract.Requires(lhs != null);
 3500      Contract.Requires(resolutionContext != null);
 2406003501      if (lhs is IdentifierExpr) {
 1187773502        var ll = (IdentifierExpr)lhs;
 1187773503        if (!ll.Var.IsMutable) {
 03504          reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable");
 03505        }
 1218233506      } else if (lhs is MemberSelectExpr) {
 03507        var ll = (MemberSelectExpr)lhs;
 03508        var field = ll.Member as Field;
 03509        if (field == null || !field.IsUserMutable) {
 03510          if (resolutionContext.InFirstPhaseConstructor && field is ConstantField cf && !cf.IsStatic && cf.Rhs == null) 
 03511            if (Expression.AsThis(ll.Obj) != null) {
 3512              // it's cool; this field can be assigned to here
 03513            } else {
 03514              reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field of 'this'");
 03515            }
 03516          } else {
 03517            reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field");
 03518          }
 03519        }
 60923520      } else if (lhs is SeqSelectExpr) {
 30463521        var ll = (SeqSelectExpr)lhs;
 30463522        ConstrainSubtypeRelation(ResolvedArrayType(ll.Seq.tok, 1, new InferredTypeProxy(), resolutionContext, true), ll.
 30463523          "LHS of array assignment must denote an array element (found {0})", ll.Seq.Type);
 30463524        if (!ll.SelectOne) {
 03525          reporter.Error(MessageSource.Resolver, ll.Seq, "cannot assign to a range of array elements (try the 'forall' s
 03526        }
 30463527      } else if (lhs is MultiSelectExpr) {
 3528        // nothing to check; this can only denote an array element
 03529      } else {
 03530        reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable or field");
 03531      }
 1218233532    }
 3533
 110193534    public void ResolveBlockStatement(BlockStmt blockStmt, ResolutionContext resolutionContext) {
 3535      Contract.Requires(blockStmt != null);
 3536      Contract.Requires(resolutionContext != null);
 3537
 110193538      if (blockStmt is DividedBlockStmt) {
 03539        var div = (DividedBlockStmt)blockStmt;
 03540        Contract.Assert(currentMethod is Constructor);  // divided bodies occur only in class constructors
 03541        Contract.Assert(!resolutionContext.InFirstPhaseConstructor);  // divided bodies are never nested
 03542        foreach (Statement ss in div.BodyInit) {
 03543          ResolveStatementWithLabels(ss, resolutionContext with { InFirstPhaseConstructor = true });
 03544        }
 03545        foreach (Statement ss in div.BodyProper) {
 03546          ResolveStatementWithLabels(ss, resolutionContext);
 03547        }
 110193548      } else {
 4021653549        foreach (Statement ss in blockStmt.Body) {
 1230363550          ResolveStatementWithLabels(ss, resolutionContext);
 1230363551        }
 110193552      }
 110193553    }
 3554
 1238673555    public void ResolveStatementWithLabels(Statement stmt, ResolutionContext resolutionContext) {
 3556      Contract.Requires(stmt != null);
 3557      Contract.Requires(resolutionContext != null);
 3558
 1238673559      enclosingStatementLabels.PushMarker();
 3560      // push labels
 2477343561      for (var l = stmt.Labels; l != null; l = l.Next) {
 03562        var lnode = l.Data;
 03563        Contract.Assert(lnode.Name != null);  // LabelNode's with .Label==null are added only during resolution of the b
 03564        var prev = enclosingStatementLabels.Find(lnode.Name);
 03565        if (prev == stmt) {
 03566          reporter.Error(MessageSource.Resolver, lnode.Tok, "duplicate label");
 03567        } else if (prev != null) {
 03568          reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows an enclosing label");
 03569        } else {
 03570          var r = enclosingStatementLabels.Push(lnode.Name, stmt);
 03571          Contract.Assert(r == Scope<Statement>.PushResult.Success);  // since we just checked for duplicates, we expect
 03572          if (DominatingStatementLabels.Find(lnode.Name) != null) {
 03573            reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows a dominating label");
 03574          } else {
 03575            var rr = DominatingStatementLabels.Push(lnode.Name, lnode);
 03576            Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expect 
 03577          }
 03578        }
 03579      }
 1238673580      ResolveStatement(stmt, resolutionContext);
 1238673581      enclosingStatementLabels.PopMarker();
 1238673582    }
 3583
 03584    void ResolveAlternatives(List<GuardedAlternative> alternatives, AlternativeLoopStmt loopToCatchBreaks, ResolutionCon
 3585      Contract.Requires(alternatives != null);
 3586      Contract.Requires(resolutionContext != null);
 3587
 3588      // first, resolve the guards
 03589      foreach (var alternative in alternatives) {
 03590        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 03591        ResolveExpression(alternative.Guard, resolutionContext);
 03592        Contract.Assert(alternative.Guard.Type != null);  // follows from postcondition of ResolveExpression
 03593        bool successfullyResolved = reporter.Count(ErrorLevel.Error) == prevErrorCount;
 03594        ConstrainTypeExprBool(alternative.Guard, "condition is expected to be of type bool, but is {0}");
 03595      }
 3596
 03597      if (loopToCatchBreaks != null) {
 03598        loopStack.Add(loopToCatchBreaks);  // push
 03599      }
 03600      foreach (var alternative in alternatives) {
 03601        scope.PushMarker();
 03602        DominatingStatementLabels.PushMarker();
 03603        if (alternative.IsBindingGuard) {
 03604          var exists = (ExistsExpr)alternative.Guard;
 03605          foreach (var v in exists.BoundVars) {
 03606            ScopePushAndReport(scope, v, "bound-variable");
 03607          }
 03608        }
 03609        ResolveAttributes(alternative, resolutionContext);
 03610        foreach (Statement ss in alternative.Body) {
 03611          ResolveStatementWithLabels(ss, resolutionContext);
 03612        }
 03613        DominatingStatementLabels.PopMarker();
 03614        scope.PopMarker();
 03615      }
 03616      if (loopToCatchBreaks != null) {
 03617        loopStack.RemoveAt(loopStack.Count - 1);  // pop
 03618      }
 03619    }
 3620
 3621    /// <summary>
 3622    /// Resolves the given call statement.
 3623    /// Assumes all LHSs have already been resolved (and checked for mutability).
 3624    /// </summary>
 74313625    void ResolveCallStmt(CallStmt s, ResolutionContext resolutionContext, Type receiverType) {
 3626      Contract.Requires(s != null);
 3627      Contract.Requires(resolutionContext != null);
 74313628      bool isInitCall = receiverType != null;
 3629
 74313630      var callee = s.Method;
 74313631      Contract.Assert(callee != null);  // follows from the invariant of CallStmt
 74313632      if (!isInitCall && callee is Constructor) {
 03633        reporter.Error(MessageSource.Resolver, s, "a constructor is allowed to be called only when an object is being al
 03634      }
 3635
 3636      // resolve left-hand sides (the right-hand sides are resolved below)
 457143637      foreach (var lhs in s.Lhs) {
 78073638        Contract.Assume(lhs.Type != null);  // a sanity check that LHSs have already been resolved
 78073639      }
 3640
 74313641      bool tryToResolve = false;
 74313642      if (callee.Outs.Count != s.Lhs.Count) {
 03643        if (isInitCall) {
 03644          reporter.Error(MessageSource.Resolver, s, "a method called as an initialization method must not have any resul
 03645        } else {
 03646          reporter.Error(MessageSource.Resolver, s, "wrong number of method result arguments (got {0}, expected {1})", s
 03647          tryToResolve = true;
 03648        }
 74313649      } else {
 74313650        if (isInitCall) {
 03651          if (callee.IsStatic) {
 03652            reporter.Error(MessageSource.Resolver, s.Tok, "a method called as an initialization method must not be 'stat
 03653          } else {
 03654            tryToResolve = true;
 03655          }
 74313656        } else if (!callee.IsStatic) {
 03657          if (!scope.AllowInstance && s.Receiver is ThisExpr) {
 3658            // The call really needs an instance, but that instance is given as 'this', which is not
 3659            // available in this context.  For more details, see comment in the resolution of a
 3660            // FunctionCallExpr.
 03661            reporter.Error(MessageSource.Resolver, s.Receiver, "'this' is not allowed in a 'static' context");
 03662          } else if (s.Receiver is StaticReceiverExpr) {
 03663            reporter.Error(MessageSource.Resolver, s.Receiver, "call to instance method requires an instance");
 03664          } else {
 03665            tryToResolve = true;
 03666          }
 74313667        } else {
 74313668          tryToResolve = true;
 74313669        }
 74313670      }
 3671
 148623672      if (tryToResolve) {
 74313673        var typeMap = s.MethodSelect.TypeArgumentSubstitutionsAtMemberDeclaration();
 3674        // resolve arguments
 74313675        ResolveActualParameters(s.Bindings, callee.Ins, s.Tok, callee, resolutionContext, typeMap,
 74313676          callee.IsStatic ? null : s.Receiver);
 3677        // type check the out-parameter arguments (in-parameters were type checked as part of ResolveActualParameters)
 382833678        for (int i = 0; i < callee.Outs.Count && i < s.Lhs.Count; i++) {
 78073679          var outFormal = callee.Outs[i];
 78073680          var it = outFormal.Type;
 78073681          Type st = it.Subst(typeMap);
 78073682          var lhs = s.Lhs[i];
 78073683          var what = GetLocationInformation(outFormal, callee.Outs.Count(), i, "method out-parameter");
 3684
 78073685          AddAssignableConstraint(
 78073686            s.Tok, lhs.Type, st,
 78073687            $"incorrect return type {what} (expected {{1}}, got {{0}})");
 78073688        }
 382833689        for (int i = 0; i < s.Lhs.Count; i++) {
 78073690          var lhs = s.Lhs[i];
 3691          // LHS must denote a mutable field.
 78073692          CheckIsLvalue(lhs.Resolved, resolutionContext);
 78073693        }
 74313694      }
 74313695      if (Contract.Exists(callee.Decreases.Expressions, e => e is WildcardExpr) && !resolutionContext.CodeContext.Allows
 03696        reporter.Error(MessageSource.Resolver, s.Tok, "a call to a possibly non-terminating method is allowed only if th
 03697      }
 74313698    }
 3699
 3700    /// <summary>
 3701    /// Resolve the actual arguments given in "bindings". Then, check that there is exactly one
 3702    /// actual for each formal, and impose assignable constraints.
 3703    /// "typeMap" is applied to the type of each formal.
 3704    /// This method should be called only once. That is, bindings.arguments is required to be null on entry to this meth
 3705    /// </summary>
 3706    void ResolveActualParameters(ActualBindings bindings, List<Formal> formals, IToken callTok, object context, Resoluti
 326743707      Dictionary<TypeParameter, Type> typeMap, Expression/*?*/ receiver) {
 3708      Contract.Requires(bindings != null);
 3709      Contract.Requires(formals != null);
 3710      Contract.Requires(callTok != null);
 3711      Contract.Requires(context is Method || context is Function || context is DatatypeCtor || context is ArrowType);
 3712      Contract.Requires(typeMap != null);
 3713      Contract.Requires(!bindings.WasResolved);
 3714
 3715      string whatKind;
 3716      string name;
 401053717      if (context is Method cMethod) {
 74313718        whatKind = cMethod.WhatKind;
 74313719        name = $"{whatKind} '{cMethod.Name}'";
 326743720      } else if (context is Function cFunction) {
 03721        whatKind = cFunction.WhatKind;
 03722        name = $"{whatKind} '{cFunction.Name}'";
 504863723      } else if (context is DatatypeCtor cCtor) {
 252433724        whatKind = "datatype constructor";
 252433725        name = $"{whatKind} '{cCtor.Name}'";
 252433726      } else {
 03727        var cArrowType = (ArrowType)context;
 03728        whatKind = "function application";
 03729        name = $"function type '{cArrowType}'";
 03730      }
 3731
 3732      // If all arguments are passed positionally, use simple error messages that talk about the count of arguments.
 988343733      var onlyPositionalArguments = bindings.ArgumentBindings.TrueForAll(binding => binding.FormalParameterName == null)
 326743734      var simpleErrorReported = false;
 653483735      if (onlyPositionalArguments) {
 988343736        var requiredParametersCount = formals.Count(f => f.DefaultValue == null);
 326743737        var actualsCounts = bindings.ArgumentBindings.Count;
 326743738        var sig = "";
 2638283739        for (int i = 0; i < formals.Count; i++) {
 661603740          sig += (", " + formals[i].Name + ": " + formals[i].Type.ToString());
 661603741        }
 610953742        if (formals.Count > 0) {
 284213743          sig = ": (" + sig[2..] + ")";
 284213744        }
 653483745        if (requiredParametersCount <= actualsCounts && actualsCounts <= formals.Count) {
 3746          // the situation is plausible
 326743747        } else if (requiredParametersCount == formals.Count) {
 3748          // this is the common, classical case of no default parameter values; generate a straightforward error message
 03749          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03750          simpleErrorReported = true;
 03751        } else if (actualsCounts < requiredParametersCount) {
 03752          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03753          simpleErrorReported = true;
 03754        } else {
 03755          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03756          simpleErrorReported = true;
 03757        }
 326743758      }
 3759
 3760      // resolve given arguments and populate the "namesToActuals" map
 326743761      var namesToActuals = new Dictionary<string, ActualBinding>();
 988343762      formals.ForEach(f => namesToActuals.Add(f.Name, null)); // a name mapping to "null" says it hasn't been filled in 
 326743763      var stillAcceptingPositionalArguments = true;
 326743764      var bindingIndex = 0;
 2965023765      foreach (var binding in bindings.ArgumentBindings) {
 661603766        var arg = binding.Actual;
 3767        // insert the actual into "namesToActuals" under an appropriate name, unless there is an error
 661603768        if (binding.FormalParameterName != null) {
 03769          var pname = binding.FormalParameterName.val;
 03770          stillAcceptingPositionalArguments = false;
 03771          if (!namesToActuals.TryGetValue(pname, out var b)) {
 03772            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"the binding named '{pname}' does not c
 03773          } else if (b == null) {
 3774            // all is good
 03775            namesToActuals[pname] = binding;
 03776          } else if (b.FormalParameterName == null) {
 03777            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"the parameter named '{pname}' is alrea
 03778          } else {
 03779            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"duplicate binding for parameter name '
 03780          }
 661603781        } else if (!stillAcceptingPositionalArguments) {
 03782          reporter.Error(MessageSource.Resolver, arg.tok, "a positional argument is not allowed to follow named argument
 1323203783        } else if (bindingIndex < formals.Count) {
 3784          // use the name of formal corresponding to this positional argument, unless the parameter is named-only
 661603785          var formal = formals[bindingIndex];
 661603786          var pname = formal.Name;
 661603787          if (formal.IsNameOnly) {
 03788            reporter.Error(MessageSource.Resolver, arg.tok,
 03789              $"nameonly parameter '{pname}' must be passed using a name binding; it cannot be passed positionally");
 03790          }
 661603791          Contract.Assert(namesToActuals[pname] == null); // we expect this, since we've only filled parameters position
 661603792          namesToActuals[pname] = binding;
 661603793        } else {
 3794          // too many positional arguments
 03795          if (onlyPositionalArguments) {
 3796            // error was reported before the "foreach" loop
 03797            Contract.Assert(simpleErrorReported);
 03798          } else if (formals.Count < bindingIndex) {
 3799            // error was reported on a previous iteration of this "foreach" loop
 03800          } else {
 03801            reporter.Error(MessageSource.Resolver, callTok,
 03802              $"wrong number of arguments ({name} expects {formals.Count}, got {bindings.ArgumentBindings.Count})");
 03803          }
 03804        }
 3805
 3806        // resolve argument
 661603807        ResolveExpression(arg, resolutionContext);
 661603808        bindingIndex++;
 661603809      }
 3810
 326743811      var actuals = new List<Expression>();
 326743812      var formalIndex = 0;
 326743813      var substMap = new Dictionary<IVariable, Expression>();
 2965023814      foreach (var formal in formals) {
 661603815        var b = namesToActuals[formal.Name];
 1323203816        if (b != null) {
 661603817          actuals.Add(b.Actual);
 661603818          substMap.Add(formal, b.Actual);
 661603819          var what = GetLocationInformation(formal,
 661603820            bindings.ArgumentBindings.Count(), bindings.ArgumentBindings.IndexOf(b),
 661603821            whatKind + (context is Method ? " in-parameter" : " parameter"));
 3822
 661603823          AddAssignableConstraint(
 661603824            callTok, formal.Type.Subst(typeMap), b.Actual.Type,
 661603825            $"incorrect argument type {what} (expected {{0}}, found {{1}})");
 661603826        } else if (formal.DefaultValue != null) {
 3827          // Note, in the following line, "substMap" is passed in, but it hasn't been fully filled in until the
 3828          // end of this foreach loop. Still, that's soon enough, because DefaultValueExpression won't use it
 3829          // until FillInDefaultValueExpressions at the end of Pass 1 of the Resolver.
 03830          var n = new DefaultValueExpression(callTok, formal, receiver, substMap, typeMap);
 03831          allDefaultValueExpressions.Add(n);
 03832          actuals.Add(n);
 03833          substMap.Add(formal, n);
 03834        } else {
 3835          // parameter has no value
 03836          if (onlyPositionalArguments) {
 3837            // a simple error message has already been reported
 03838            Contract.Assert(simpleErrorReported);
 03839          } else {
 03840            var formalDescription = whatKind + (context is Method ? " in-parameter" : " parameter");
 03841            var nameWithIndex = formal.HasName && formal is not ImplicitFormal ? "'" + formal.Name + "'" : "";
 03842            if (formals.Count > 1 || nameWithIndex == "") {
 03843              nameWithIndex += nameWithIndex == "" ? "" : " ";
 03844              nameWithIndex += $"at index {formalIndex}";
 03845            }
 03846            var message = $"{formalDescription} {nameWithIndex} requires an argument of type {formal.Type}";
 03847            reporter.Error(MessageSource.Resolver, callTok, message);
 03848          }
 03849        }
 661603850        formalIndex++;
 661603851      }
 3852
 326743853      bindings.AcceptArgumentExpressionsAsExactParameterList(actuals);
 326743854    }
 3855
 739673856    private static string GetLocationInformation(Formal parameter, int bindingCount, int bindingIndex, string formalDesc
 739673857      var displayName = parameter.HasName && parameter is not ImplicitFormal;
 739673858      var description = "";
 1394903859      if (bindingCount > 1) {
 655233860        description += $"at index {bindingIndex} ";
 655233861      }
 3862
 739673863      description += $"for {formalDescription}";
 3864
 1479343865      if (displayName) {
 739673866        description += $" '{parameter.Name}'";
 739673867      }
 3868
 739673869      return description;
 739673870    }
 3871
 3872    /// <summary>
 3873    /// To resolve "id" in expression "E . id", do:
 3874    ///  * If E denotes a module name M:
 3875    ///      0. Member of module M:  sub-module (including submodules of imports), class, datatype, etc.
 3876    ///         (if two imported types have the same name, an error message is produced here)
 3877    ///      1. Static member of M._default denoting an async task type
 3878    ///    (Note that in contrast to ResolveNameSegment_Type, imported modules, etc. are ignored)
 3879    ///  * If E denotes a type:
 3880    ///      2. a. Member of that type denoting an async task type, or:
 3881    ///         b. If allowDanglingDotName:
 3882    ///            Return the type "E" and the given "expr", letting the caller try to make sense of the final dot-name.
 3883    ///
 3884    /// Note: 1 and 2a are not used now, but they will be of interest when async task types are supported.
 3885    /// </summary>
 03886    ResolveTypeReturn ResolveDotSuffix_Type(ExprDotName expr, ResolutionContext resolutionContext, bool allowDanglingDot
 3887      Contract.Requires(expr != null);
 3888      Contract.Requires(!expr.WasResolved());
 3889      Contract.Requires(expr.Lhs is NameSegment || expr.Lhs is ExprDotName);
 3890      Contract.Requires(resolutionContext != null);
 3891      Contract.Ensures(Contract.Result<ResolveTypeReturn>() == null || allowDanglingDotName);
 3892
 3893      // resolve the LHS expression
 03894      if (expr.Lhs is NameSegment) {
 03895        ResolveNameSegment_Type((NameSegment)expr.Lhs, resolutionContext, option, defaultTypeArguments);
 03896      } else {
 03897        ResolveDotSuffix_Type((ExprDotName)expr.Lhs, resolutionContext, false, option, defaultTypeArguments);
 03898      }
 3899
 03900      if (expr.OptTypeArguments != null) {
 03901        foreach (var ty in expr.OptTypeArguments) {
 03902          ResolveType(expr.tok, ty, resolutionContext, option, defaultTypeArguments);
 03903        }
 03904      }
 3905
 03906      Expression r = null;  // the resolved expression, if successful
 3907
 03908      var lhs = expr.Lhs.Resolved;
 03909      if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 03910        var ri = (Resolver_IdentifierExpr)lhs;
 03911        var sig = ((ModuleDecl)ri.Decl).AccessibleSignature(useCompileSignatures);
 03912        sig = GetSignature(sig);
 3913        // For 0:
 3914
 03915        if (sig.TopLevels.TryGetValue(expr.SuffixName, out var decl)) {
 3916          // ----- 0. Member of the specified module
 03917          if (decl is AmbiguousTopLevelDecl) {
 03918            var ad = (AmbiguousTopLevelDecl)decl;
 03919            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 03920          } else {
 3921            // We have found a module name or a type name.  We create a temporary expression that will never be seen by 
 3922            // or verifier, just to have a placeholder where we can recorded what we have found.
 03923            r = CreateResolver_IdentifierExpr(expr.tok, expr.SuffixName, expr.OptTypeArguments, decl);
 03924          }
 3925#if ASYNC_TASK_TYPES
 3926        } else if (sig.StaticMembers.TryGetValue(expr.SuffixName, out member)) {
 3927          // ----- 1. static member of the specified module
 3928          Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of th
 3929          if (ReallyAmbiguousThing(ref member)) {
 3930            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 3931          } else {
 3932            var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 3933            r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMetho
 3934          }
 3935#endif
 03936        } else {
 03937          reporter.Error(MessageSource.Resolver, expr.tok, "module '{0}' does not declare a type '{1}'", ri.Decl.Name, e
 03938        }
 3939
 03940      } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 03941        var ri = (Resolver_IdentifierExpr)lhs;
 3942        // ----- 2. Look up name in type
 03943        var ty = new UserDefinedType(ri.tok, ri.Decl.Name, ri.Decl, ri.TypeArgs);
 03944        if (allowDanglingDotName && ty.IsRefType) {
 03945          return new ResolveTypeReturn(ty, expr);
 3946        }
 03947        if (r == null) {
 03948          reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in type '{1}' or cannot be part 
 03949        }
 03950      }
 3951
 03952      if (r == null) {
 3953        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 03954        expr.Type = new InferredTypeProxy();
 03955      } else {
 03956        expr.ResolvedExpression = r;
 03957        expr.Type = r.Type;
 03958      }
 03959      return null;
 03960    }
 3961
 2112083962    internal Resolver_IdentifierExpr CreateResolver_IdentifierExpr(IToken tok, string name, List<Type> optTypeArguments,
 3963      Contract.Requires(tok != null);
 3964      Contract.Requires(name != null);
 3965      Contract.Requires(decl != null);
 3966      Contract.Ensures(Contract.Result<Resolver_IdentifierExpr>() != null);
 3967
 4224163968      if (!moduleInfo.IsAbstract) {
 2112083969        if (decl is ModuleDecl md && md.Signature.IsAbstract) {
 03970          reporter.Error(MessageSource.Resolver, tok, "a compiled module is not allowed to use an abstract module ({0})"
 03971        }
 2112083972      }
 2112083973      var n = optTypeArguments == null ? 0 : optTypeArguments.Count;
 2605183974      if (optTypeArguments != null) {
 3975        // type arguments were supplied; they must be equal in number to those expected
 493103976        if (n != decl.TypeArgs.Count) {
 03977          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of {1}) passed to {2}
 03978        }
 493103979      }
 2112083980      List<Type> tpArgs = new List<Type>();
 6771613981      for (int i = 0; i < decl.TypeArgs.Count; i++) {
 849153982        tpArgs.Add(i < n ? optTypeArguments[i] : new InferredTypeProxy());
 849153983      }
 2112083984      return new Resolver_IdentifierExpr(tok, decl, tpArgs);
 2112083985    }
 3986
 2544663987    public void ResolveStatement(Statement stmt, ResolutionContext resolutionContext) {
 3988      Contract.Requires(stmt != null);
 3989      Contract.Requires(resolutionContext != null);
 2676193990      if (stmt is ICanResolve canResolve) {
 131533991        canResolve.Resolve(this, resolutionContext);
 131533992        return;
 3993      }
 4819143994      if (!(stmt is ForallStmt || stmt is ForLoopStmt)) {  // "forall" and "for" statements do their own attribute resol
 2406013995        ResolveAttributes(stmt, resolutionContext);
 2406013996      }
 2436033997      if (stmt is PredicateStmt) {
 22903998        PredicateStmt s = (PredicateStmt)stmt;
 22903999        var assertStmt = stmt as AssertStmt;
 22904000        if (assertStmt != null && assertStmt.Label != null) {
 04001          if (DominatingStatementLabels.Find(assertStmt.Label.Name) != null) {
 04002            reporter.Error(MessageSource.Resolver, assertStmt.Label.Tok, "assert label shadows a dominating label");
 04003          } else {
 04004            var rr = DominatingStatementLabels.Push(assertStmt.Label.Name, assertStmt.Label);
 04005            Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expect 
 04006          }
 04007        }
 4008
 22904009        if (assertStmt != null && Attributes.Find(assertStmt.Attributes, "only") is UserSuppliedAttributes attribute) {
 04010          reporter.Warning(MessageSource.Verifier, ResolutionErrors.ErrorId.r_assert_only_assumes_others.ToString(), att
 04011            "Assertion with {:only} temporarily transforms other assertions into assumptions");
 04012          if (attribute.Args.Count >= 1
 04013              && attribute.Args[0] is LiteralExpr { Value: string value }
 04014              && value != "before" && value != "after") {
 04015            reporter.Warning(MessageSource.Verifier, ResolutionErrors.ErrorId.r_assert_only_before_after.ToString(), att
 04016              "{:only} only accepts \"before\" or \"after\" as an optional argument");
 04017          }
 04018        }
 22904019        ResolveExpression(s.Expr, resolutionContext);
 22904020        Contract.Assert(s.Expr.Type != null);  // follows from postcondition of ResolveExpression
 22904021        ConstrainTypeExprBool(s.Expr, "condition is expected to be of type bool, but is {0}");
 22904022        if (assertStmt != null && assertStmt.Proof != null) {
 4023          // clear the labels for the duration of checking the proof body, because break statements are not allowed to l
 04024          var prevLblStmts = enclosingStatementLabels;
 04025          var prevLoopStack = loopStack;
 04026          enclosingStatementLabels = new Scope<Statement>(Options);
 04027          loopStack = new List<Statement>();
 04028          ResolveStatement(assertStmt.Proof, resolutionContext);
 04029          enclosingStatementLabels = prevLblStmts;
 04030          loopStack = prevLoopStack;
 04031        }
 22904032        var expectStmt = stmt as ExpectStmt;
 34354033        if (expectStmt != null) {
 18254034          if (expectStmt.Message == null) {
 6804035            expectStmt.Message = new StringLiteralExpr(s.Tok, "expectation violation", false);
 6804036          }
 11454037          ResolveExpression(expectStmt.Message, resolutionContext);
 11454038          Contract.Assert(expectStmt.Message.Type != null);  // follows from postcondition of ResolveExpression
 11454039        }
 4040
 2429984041      } else if (stmt is PrintStmt) {
 16854042        var s = (PrintStmt)stmt;
 2088234043        s.Args.Iter(e => ResolveExpression(e, resolutionContext));
 4044
 2390234045      } else if (stmt is RevealStmt) {
 04046        var s = (RevealStmt)stmt;
 04047        foreach (var expr in s.Exprs) {
 04048          var name = RevealStmt.SingleName(expr);
 04049          var labeledAssert = name == null ? null : DominatingStatementLabels.Find(name) as AssertLabel;
 04050          if (labeledAssert != null) {
 04051            s.LabeledAsserts.Add(labeledAssert);
 04052          } else {
 04053            var revealResolutionContext = resolutionContext with { InReveal = true };
 04054            if (expr is ApplySuffix) {
 04055              var e = (ApplySuffix)expr;
 04056              var methodCallInfo = ResolveApplySuffix(e, revealResolutionContext, true);
 04057              if (methodCallInfo == null) {
 04058                reporter.Error(MessageSource.Resolver, expr.tok, "expression has no reveal lemma");
 04059              } else if (methodCallInfo.Callee.Member is TwoStateLemma && !revealResolutionContext.IsTwoState) {
 04060                reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "a two-state function can only be revealed in
 04061              } else if (methodCallInfo.Callee.AtLabel != null) {
 04062                Contract.Assert(methodCallInfo.Callee.Member is TwoStateLemma);
 04063                reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "to reveal a two-state function, do not list 
 04064              } else {
 04065                var call = new CallStmt(s.RangeToken, new List<Expression>(), methodCallInfo.Callee, methodCallInfo.Actu
 04066                s.ResolvedStatements.Add(call);
 04067              }
 04068            } else if (expr is NameSegment or ExprDotName) {
 04069              if (expr is NameSegment) {
 04070                ResolveNameSegment((NameSegment)expr, true, null, revealResolutionContext, true);
 04071              } else {
 04072                ResolveDotSuffix((ExprDotName)expr, true, null, revealResolutionContext, true);
 04073              }
 04074              MemberSelectExpr callee = (MemberSelectExpr)((ConcreteSyntaxExpression)expr).ResolvedExpression;
 04075              if (callee == null) {
 04076              } else if (callee.Member is Lemma or TwoStateLemma && Attributes.Contains(callee.Member.Attributes, "axiom
 4077                //The revealed member is a function
 04078                reporter.Error(MessageSource.Resolver, callee.tok, "to reveal a function ({0}), append parentheses", cal
 04079              } else {
 04080                var call = new CallStmt(s.RangeToken, new List<Expression>(), callee, new List<ActualBinding>(), expr.to
 04081                s.ResolvedStatements.Add(call);
 04082              }
 04083            } else {
 04084              ResolveExpression(expr, revealResolutionContext);
 04085            }
 04086          }
 04087        }
 04088        foreach (var a in s.ResolvedStatements) {
 04089          ResolveStatement(a, resolutionContext);
 04090        }
 2376004091      } else if (stmt is BreakStmt) {
 2624092        var s = (BreakStmt)stmt;
 2624093        if (s.TargetLabel != null) {
 04094          Statement target = enclosingStatementLabels.Find(s.TargetLabel.val);
 04095          if (target == null) {
 04096            reporter.Error(MessageSource.Resolver, s.TargetLabel, $"{s.Kind} label is undefined or not in scope: {s.Targ
 04097          } else if (s.IsContinue && !(target is LoopStmt)) {
 04098            reporter.Error(MessageSource.Resolver, s.TargetLabel, $"continue label must designate a loop: {s.TargetLabel
 04099          } else {
 04100            s.TargetStmt = target;
 04101          }
 2624102        } else {
 2624103          Contract.Assert(1 <= s.BreakAndContinueCount); // follows from BreakStmt class invariant and the guard for thi
 2624104          var jumpStmt = s.BreakAndContinueCount == 1 ?
 2624105            $"a non-labeled '{s.Kind}' statement" :
 2624106            $"a '{Util.Repeat(s.BreakAndContinueCount - 1, "break ")}{s.Kind}' statement";
 2624107          if (loopStack.Count == 0) {
 04108            reporter.Error(MessageSource.Resolver, s, $"{jumpStmt} is allowed only in loops");
 2624109          } else if (loopStack.Count < s.BreakAndContinueCount) {
 04110            reporter.Error(MessageSource.Resolver, s,
 04111              $"{jumpStmt} is allowed only in contexts with {s.BreakAndContinueCount} enclosing loops, but the current c
 2624112          } else {
 2624113            Statement target = loopStack[loopStack.Count - s.BreakAndContinueCount];
 5194114            if (target.Labels == null) {
 4115              // make sure there is a label, because the compiler and translator will want to see a unique ID
 2574116              target.Labels = new LList<Label>(new Label(target.Tok, null), null);
 2574117            }
 2624118            s.TargetStmt = target;
 2624119          }
 2624120        }
 4121
 2452774122      } else if (stmt is ProduceStmt) {
 79394123        var kind = stmt is YieldStmt ? "yield" : "return";
 79394124        if (stmt is YieldStmt && !(resolutionContext.CodeContext is IteratorDecl)) {
 04125          reporter.Error(MessageSource.Resolver, stmt, "yield statement is allowed only in iterators");
 79394126        } else if (stmt is ReturnStmt && !(resolutionContext.CodeContext is Method)) {
 04127          reporter.Error(MessageSource.Resolver, stmt, "return statement is allowed only in method");
 79394128        } else if (resolutionContext.InFirstPhaseConstructor) {
 04129          reporter.Error(MessageSource.Resolver, stmt, "return statement is not allowed before 'new;' in a constructor")
 04130        }
 79394131        var s = (ProduceStmt)stmt;
 142704132        if (s.Rhss != null) {
 63314133          var cmc = resolutionContext.CodeContext as IMethodCodeContext;
 63314134          if (cmc == null) {
 4135            // an error has already been reported above
 63314136          } else if (cmc.Outs.Count != s.Rhss.Count) {
 04137            reporter.Error(MessageSource.Resolver, s, "number of {2} parameters does not match declaration (found {0}, e
 63314138          } else {
 63314139            Contract.Assert(s.Rhss.Count > 0);
 4140            // Create a hidden update statement using the out-parameter formals, resolve the RHS, and check that the RHS
 63314141            List<Expression> formals = new List<Expression>();
 444814142            foreach (Formal f in cmc.Outs) {
 4143              Expression produceLhs;
 169924144              if (stmt is ReturnStmt) {
 84964145                var ident = new ImplicitIdentifierExpr(f.tok, f.Name);
 4146                // resolve it here to avoid capture into more closely declared local variables
 84964147                ident.Var = f;
 84964148                ident.Type = ident.Var.Type;
 84964149                Contract.Assert(f.Type != null);
 84964150                produceLhs = ident;
 84964151              } else {
 04152                var yieldIdent = new MemberSelectExpr(f.tok, new ImplicitThisExpr(f.tok), f.Name);
 04153                ResolveExpression(yieldIdent, resolutionContext);
 04154                produceLhs = yieldIdent;
 04155              }
 84964156              formals.Add(produceLhs);
 84964157            }
 63314158            s.HiddenUpdate = new UpdateStmt(s.RangeToken, formals, s.Rhss, true);
 4159            // resolving the update statement will check for return/yield statement specifics.
 63314160            ResolveStatement(s.HiddenUpdate, resolutionContext);
 63314161          }
 79394162        } else {// this is a regular return/yield statement.
 16084163          s.HiddenUpdate = null;
 16084164        }
 3374964165      } else if (stmt is VarDeclStmt) {
 1004204166        var s = (VarDeclStmt)stmt;
 4167        // We have four cases.
 1004204168        Contract.Assert(s.Update == null || s.Update is AssignSuchThatStmt || s.Update is UpdateStmt || s.Update is Assi
 4169        // 0.  There is no .Update.  This is easy, we will just resolve the locals.
 4170        // 1.  The .Update is an AssignSuchThatStmt.  This is also straightforward:  first
 4171        //     resolve the locals, which adds them to the scope, and then resolve the .Update.
 4172        // 2.  The .Update is an UpdateStmt, which, resolved, means either a CallStmt or a bunch
 4173        //     of parallel AssignStmt's.  Here, the right-hand sides should be resolved before
 4174        //     the local variables have been added to the scope, but the left-hand sides should
 4175        //     resolve to the newly introduced variables.
 4176        // 3.  The .Update is a ":-" statement, for which resolution does two steps:
 4177        //     First, desugar, then run the regular resolution on the desugared AST.
 4178        // To accommodate these options, we first reach into the UpdateStmt, if any, to resolve
 4179        // the left-hand sides of the UpdateStmt.  This will have the effect of shielding them
 4180        // from a subsequent resolution (since expression resolution will do nothing if the .Type
 4181        // field is already assigned.
 4182        // Alright, so it is:
 4183
 4184        // Resolve the types of the locals
 6138514185        foreach (var local in s.Locals) {
 1041974186          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 1041974187          ResolveType(local.Tok, local.OptionalType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 2083944188          if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 1041974189            local.type = local.OptionalType;
 1041974190          } else {
 04191            local.type = new InferredTypeProxy();
 04192          }
 1041974193        }
 4194        // Resolve the UpdateStmt, if any
 2008404195        if (s.Update is UpdateStmt) {
 1004204196          var upd = (UpdateStmt)s.Update;
 4197          // resolve the LHS
 1004204198          Contract.Assert(upd.Lhss.Count == s.Locals.Count);
 5134314199          for (int i = 0; i < upd.Lhss.Count; i++) {
 1041974200            var local = s.Locals[i];
 1041974201            var lhs = (IdentifierExpr)upd.Lhss[i];  // the LHS in this case will be an IdentifierExpr, because that's ho
 1041974202            Contract.Assert(lhs.Type == null);  // not yet resolved
 1041974203            lhs.Var = local;
 1041974204            lhs.Type = local.Type;
 1041974205          }
 4206          // resolve the whole thing
 1004204207          s.Update.Resolve(this, resolutionContext);
 1004204208        }
 4209
 1004204210        if (s.Update is AssignOrReturnStmt) {
 04211          var assignOrRet = (AssignOrReturnStmt)s.Update;
 4212          // resolve the LHS
 04213          Contract.Assert(assignOrRet.Lhss.Count == s.Locals.Count);
 04214          for (int i = 0; i < s.Locals.Count; i++) {
 04215            var local = s.Locals[i];
 04216            var lhs = (IdentifierExpr)assignOrRet
 04217              .Lhss[i]; // the LHS in this case will be an IdentifierExpr, because that's how the parser creates the Var
 04218            Contract.Assert(lhs.Type == null); // not yet resolved
 04219            lhs.Var = local;
 04220            lhs.Type = local.Type;
 04221          }
 4222
 4223          // resolve the whole thing
 04224          assignOrRet.Resolve(this, resolutionContext);
 04225        }
 4226        // Add the locals to the scope
 6138514227        foreach (var local in s.Locals) {
 1041974228          ScopePushAndReport(scope, local, "local-variable");
 1041974229        }
 4230        // With the new locals in scope, it's now time to resolve the attributes on all the locals
 6138514231        foreach (var local in s.Locals) {
 1041974232          ResolveAttributes(local, resolutionContext);
 1041974233        }
 4234        // Resolve the AssignSuchThatStmt, if any
 1004204235        if (s.Update is AssignSuchThatStmt assignSuchThatStmt) {
 04236          assignSuchThatStmt.Resolve(this, resolutionContext);
 04237        }
 2291374238      } else if (stmt is VarDeclPattern) {
 04239        VarDeclPattern s = (VarDeclPattern)stmt;
 04240        foreach (var local in s.LocalVars) {
 04241          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04242          ResolveType(local.Tok, local.OptionalType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04243          if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 04244            local.type = local.OptionalType;
 04245          } else {
 04246            local.type = new InferredTypeProxy();
 04247          }
 04248        }
 04249        ResolveExpression(s.RHS, resolutionContext);
 04250        ResolveCasePattern(s.LHS, s.RHS.Type, resolutionContext);
 4251        // Check for duplicate names now, because not until after resolving the case pattern do we know if identifiers i
 04252        var c = 0;
 04253        foreach (var bv in s.LHS.Vars) {
 04254          ScopePushAndReport(scope, bv, "local_variable");
 04255          c++;
 04256        }
 04257        if (c == 0) {
 4258          // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constant li
 04259          reporter.Error(MessageSource.Resolver, s.LHS.tok, "LHS is a constant literal; to be legal, it must introduce a
 04260        }
 2427334261      } else if (stmt is AssignStmt) {
 1140164262        AssignStmt s = (AssignStmt)stmt;
 1140164263        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 1140164264        ResolveExpression(s.Lhs, resolutionContext);  // allow ghosts for now, tighted up below
 1140164265        bool lhsResolvedSuccessfully = reporter.Count(ErrorLevel.Error) == prevErrorCount;
 1140164266        Contract.Assert(s.Lhs.Type != null);  // follows from postcondition of ResolveExpression
 4267        // check that LHS denotes a mutable variable or a field
 1140164268        var lhs = s.Lhs.Resolved;
 2249864269        if (lhs is IdentifierExpr) {
 1109704270          IVariable var = ((IdentifierExpr)lhs).Var;
 1109704271          if (var == null) {
 4272            // the LHS didn't resolve correctly; some error would already have been reported
 1109704273          } else {
 1109704274            CheckIsLvalue(lhs, resolutionContext);
 1109704275          }
 1140164276        } else if (lhs is MemberSelectExpr) {
 04277          var fse = (MemberSelectExpr)lhs;
 04278          if (fse.Member != null) {  // otherwise, an error was reported above
 04279            CheckIsLvalue(fse, resolutionContext);
 04280          }
 60924281        } else if (lhs is SeqSelectExpr) {
 30464282          var slhs = (SeqSelectExpr)lhs;
 4283          // LHS is fine, provided the "sequence" is really an array
 60924284          if (lhsResolvedSuccessfully) {
 30464285            Contract.Assert(slhs.Seq.Type != null);
 30464286            CheckIsLvalue(slhs, resolutionContext);
 30464287          }
 30464288        } else if (lhs is MultiSelectExpr) {
 04289          CheckIsLvalue(lhs, resolutionContext);
 04290        } else {
 04291          CheckIsLvalue(lhs, resolutionContext);
 04292        }
 1140164293        Type lhsType = s.Lhs.Type;
 2218834294        if (s.Rhs is ExprRhs) {
 1078674295          ExprRhs rr = (ExprRhs)s.Rhs;
 1078674296          ResolveExpression(rr.Expr, resolutionContext);
 1078674297          Contract.Assert(rr.Expr.Type != null);  // follows from postcondition of ResolveExpression
 4298
 1163634299          if (s.Lhs is ImplicitIdentifierExpr { Var: Formal { InParam: false } }) {
 84964300            AddAssignableConstraint(stmt.Tok, lhsType, rr.Expr.Type, "Method return value mismatch (expected {0}, got {1
 1078674301          } else {
 993714302            AddAssignableConstraint(stmt.Tok, lhsType, rr.Expr.Type, "RHS (of type {1}) not assignable to LHS (of type {
 993714303          }
 1201654304        } else if (s.Rhs is TypeRhs) {
 61494305          TypeRhs rr = (TypeRhs)s.Rhs;
 61494306          Type t = ResolveTypeRhs(rr, stmt, resolutionContext);
 61494307          AddAssignableConstraint(stmt.Tok, lhsType, t, "type {1} is not assignable to LHS (of type {0})");
 61494308        } else if (s.Rhs is HavocRhs) {
 4309          // nothing else to do
 04310        } else {
 04311          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected RHS
 4312        }
 4313
 1361484314      } else if (stmt is CallStmt) {
 74314315        CallStmt s = (CallStmt)stmt;
 74314316        ResolveCallStmt(s, resolutionContext, null);
 4317
 183534318      } else if (stmt is BlockStmt) {
 36524319        var s = (BlockStmt)stmt;
 36524320        scope.PushMarker();
 36524321        ResolveBlockStatement(s, resolutionContext);
 36524322        scope.PopMarker();
 4323
 94064324      } else if (stmt is IfStmt) {
 21364325        IfStmt s = (IfStmt)stmt;
 42724326        if (s.Guard != null) {
 21364327          ResolveExpression(s.Guard, resolutionContext);
 21364328          Contract.Assert(s.Guard.Type != null);  // follows from postcondition of ResolveExpression
 21364329          ConstrainTypeExprBool(s.Guard, "condition is expected to be of type bool, but is {0}");
 21364330        }
 4331
 21364332        scope.PushMarker();
 21364333        if (s.IsBindingGuard) {
 04334          var exists = (ExistsExpr)s.Guard;
 04335          foreach (var v in exists.BoundVars) {
 04336            ScopePushAndReport(scope, v, "bound-variable");
 04337          }
 04338        }
 21364339        DominatingStatementLabels.PushMarker();
 21364340        ResolveBlockStatement(s.Thn, resolutionContext);
 21364341        DominatingStatementLabels.PopMarker();
 21364342        scope.PopMarker();
 4343
 34754344        if (s.Els != null) {
 13394345          DominatingStatementLabels.PushMarker();
 13394346          ResolveStatement(s.Els, resolutionContext);
 13394347          DominatingStatementLabels.PopMarker();
 13394348        }
 4349
 36184350      } else if (stmt is AlternativeStmt) {
 04351        var s = (AlternativeStmt)stmt;
 04352        ResolveAlternatives(s.Alternatives, null, resolutionContext);
 4353
 29644354      } else if (stmt is OneBodyLoopStmt) {
 14824355        var s = (OneBodyLoopStmt)stmt;
 22524356        if (s is WhileStmt whileS && whileS.Guard != null) {
 7704357          ResolveExpression(whileS.Guard, resolutionContext);
 7704358          Contract.Assert(whileS.Guard.Type != null);  // follows from postcondition of ResolveExpression
 7704359          ConstrainTypeExprBool(whileS.Guard, "condition is expected to be of type bool, but is {0}");
 21944360        } else if (s is ForLoopStmt forS) {
 7124361          var loopIndex = forS.LoopIndex;
 7124362          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 7124363          ResolveType(loopIndex.Tok, loopIndex.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 7124364          var err = new TypeConstraint.ErrorMsgWithToken(loopIndex.Tok, "index variable is expected to be of an integer 
 7124365          ConstrainToIntegerType(loopIndex.Tok, loopIndex.Type, false, err);
 4366
 7124367          ResolveExpression(forS.Start, resolutionContext);
 7124368          AddAssignableConstraint(forS.Start.tok, forS.LoopIndex.Type, forS.Start.Type, "lower bound (of type {1}) not a
 14244369          if (forS.End != null) {
 7124370            ResolveExpression(forS.End, resolutionContext);
 7124371            AddAssignableConstraint(forS.End.tok, forS.LoopIndex.Type, forS.End.Type, "upper bound (of type {1}) not ass
 7124372            if (forS.Decreases.Expressions.Count != 0) {
 04373              reporter.Error(MessageSource.Resolver, forS.Decreases.Expressions[0].tok,
 04374                "a 'for' loop is allowed an explicit 'decreases' clause only if the end-expression is '*'");
 04375            }
 7124376          } else if (forS.Decreases.Expressions.Count == 0 && !resolutionContext.CodeContext.AllowsNontermination) {
 4377            // note, the following error message is also emitted elsewhere (if the loop bears a "decreases *")
 04378            reporter.Error(MessageSource.Resolver, forS.Tok,
 04379              "a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be p
 04380              " (or you can add a 'decreases' clause to this 'for' loop if you want to prove that it does indeed termina
 04381          }
 4382
 4383          // Create a new scope, add the local to the scope, and resolve the attributes
 7124384          scope.PushMarker();
 7124385          ScopePushAndReport(scope, loopIndex, "index-variable");
 7124386          ResolveAttributes(s, resolutionContext);
 7124387        }
 4388
 14824389        ResolveLoopSpecificationComponents(s.Invariants, s.Decreases, s.Mod, resolutionContext);
 4390
 29644391        if (s.Body != null) {
 14824392          loopStack.Add(s);  // push
 14824393          DominatingStatementLabels.PushMarker();
 14824394          ResolveStatement(s.Body, resolutionContext);
 14824395          DominatingStatementLabels.PopMarker();
 14824396          loopStack.RemoveAt(loopStack.Count - 1);  // pop
 14824397        }
 4398
 21944399        if (s is ForLoopStmt) {
 7124400          scope.PopMarker();
 7124401        }
 4402
 14824403      } else if (stmt is AlternativeLoopStmt) {
 04404        var s = (AlternativeLoopStmt)stmt;
 04405        ResolveAlternatives(s.Alternatives, s, resolutionContext);
 04406        ResolveLoopSpecificationComponents(s.Invariants, s.Decreases, s.Mod, resolutionContext);
 4407
 04408      } else if (stmt is ForallStmt) {
 04409        var s = (ForallStmt)stmt;
 4410
 04411        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04412        scope.PushMarker();
 04413        foreach (BoundVar v in s.BoundVars) {
 04414          ScopePushAndReport(scope, v, "local-variable");
 04415          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04416        }
 04417        ResolveExpression(s.Range, resolutionContext);
 04418        Contract.Assert(s.Range.Type != null);  // follows from postcondition of ResolveExpression
 04419        ConstrainTypeExprBool(s.Range, "range restriction in forall statement must be of type bool (instead got {0})");
 04420        foreach (var ens in s.Ens) {
 04421          ResolveExpression(ens.E, resolutionContext);
 04422          Contract.Assert(ens.E.Type != null);  // follows from postcondition of ResolveExpression
 04423          ConstrainTypeExprBool(ens.E, "ensures condition is expected to be of type bool, but is {0}");
 04424        }
 4425        // Since the range and postconditions are more likely to infer the types of the bound variables, resolve them
 4426        // first (above) and only then resolve the attributes (below).
 04427        ResolveAttributes(s, resolutionContext);
 4428
 04429        if (s.Body != null) {
 4430          // clear the labels for the duration of checking the body, because break statements are not allowed to leave a
 04431          var prevLblStmts = enclosingStatementLabels;
 04432          var prevLoopStack = loopStack;
 04433          enclosingStatementLabels = new Scope<Statement>(Options);
 04434          loopStack = new List<Statement>();
 04435          ResolveStatement(s.Body, resolutionContext);
 04436          enclosingStatementLabels = prevLblStmts;
 04437          loopStack = prevLoopStack;
 04438        }
 04439        scope.PopMarker();
 4440
 04441        if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 4442          // determine the Kind and run some additional checks on the body
 04443          if (s.Ens.Count != 0) {
 4444            // The only supported kind with ensures clauses is Proof.
 04445            s.Kind = ForallStmt.BodyKind.Proof;
 04446          } else {
 4447            // There are three special cases:
 4448            // * Assign, which is the only kind of the forall statement that allows a heap update.
 4449            // * Call, which is a single call statement with no side effects or output parameters.
 4450            // * A single calc statement, which is a special case of Proof where the postcondition can be inferred.
 4451            // The effect of Assign and the postcondition of Call will be seen outside the forall
 4452            // statement.
 04453            Statement s0 = s.S0;
 04454            if (s0 is AssignStmt) {
 04455              s.Kind = ForallStmt.BodyKind.Assign;
 4456
 04457              var rhs = ((AssignStmt)s0).Rhs;
 04458              if (rhs is TypeRhs) {
 04459                reporter.Error(MessageSource.Resolver, rhs.Tok, "new allocation not supported in aggregate assignments")
 04460              }
 4461
 04462            } else if (s0 is CallStmt) {
 04463              s.Kind = ForallStmt.BodyKind.Call;
 04464              var call = (CallStmt)s.S0;
 04465              var method = call.Method;
 4466              // if the called method is not in the same module as the ForallCall stmt
 4467              // don't convert it to ForallExpression since the inlined called method's
 4468              // ensure clause might not be resolved correctly(test\dafny3\GenericSort.dfy)
 04469              if (method.EnclosingClass.EnclosingModuleDefinition != resolutionContext.CodeContext.EnclosingModule) {
 04470                s.CanConvert = false;
 04471              }
 4472              // Additional information (namely, the postcondition of the call) will be reported later. But it cannot be
 4473              // done yet, because the specification of the callee may not have been resolved yet.
 04474            } else if (s0 is CalcStmt) {
 04475              s.Kind = ForallStmt.BodyKind.Proof;
 4476              // add the conclusion of the calc as a free postcondition
 04477              var result = ((CalcStmt)s0).Result;
 04478              s.Ens.Add(new AttributedExpression(result));
 04479              reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(Options, result));
 04480            } else {
 04481              s.Kind = ForallStmt.BodyKind.Proof;
 04482              if (s.Body is BlockStmt && ((BlockStmt)s.Body).Body.Count == 0) {
 4483                // an empty statement, so don't produce any warning
 04484              } else {
 04485                reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, s.Tok, "the conclusion of the body of thi
 04486              }
 04487            }
 04488          }
 4489
 04490          if (s.ForallExpressions != null) {
 04491            foreach (Expression expr in s.ForallExpressions) {
 04492              ResolveExpression(expr, resolutionContext);
 04493            }
 04494          }
 04495        }
 4496
 04497      } else if (stmt is ModifyStmt) {
 04498        var s = (ModifyStmt)stmt;
 04499        ResolveAttributes(s.Mod, resolutionContext);
 04500        foreach (FrameExpression fe in s.Mod.Expressions) {
 04501          ResolveFrameExpression(fe, FrameExpressionUse.Modifies, resolutionContext);
 04502        }
 04503        if (s.Body != null) {
 04504          ResolveBlockStatement(s.Body, resolutionContext);
 04505        }
 4506
 04507      } else if (stmt is CalcStmt) {
 04508        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 04509        CalcStmt s = (CalcStmt)stmt;
 4510        // figure out s.Op
 04511        Contract.Assert(s.Op == null);  // it hasn't been set yet
 04512        if (s.UserSuppliedOp != null) {
 04513          s.Op = s.UserSuppliedOp;
 04514        } else {
 04515          s.Op = s.GetInferredDefaultOp() ?? CalcStmt.DefaultOp;
 04516          reporter.Info(MessageSource.Resolver, s.Tok, s.Op.ToString());
 04517        }
 4518
 04519        if (s.Lines.Count > 0) {
 04520          Type lineType = new InferredTypeProxy();
 04521          var e0 = s.Lines.First();
 04522          ResolveExpression(e0, resolutionContext);
 04523          Contract.Assert(e0.Type != null);  // follows from postcondition of ResolveExpression
 04524          var err = new TypeConstraint.ErrorMsgWithToken(e0.tok, "all lines in a calculation must have the same type (go
 04525          ConstrainSubtypeRelation(lineType, e0.Type, err);
 04526          for (int i = 1; i < s.Lines.Count; i++) {
 04527            var e1 = s.Lines[i];
 04528            ResolveExpression(e1, resolutionContext);
 04529            Contract.Assert(e1.Type != null);  // follows from postcondition of ResolveExpression
 4530            // reuse the error object if we're on the dummy line; this prevents a duplicate error message
 04531            if (i < s.Lines.Count - 1) {
 04532              err = new TypeConstraint.ErrorMsgWithToken(e1.tok, "all lines in a calculation must have the same type (go
 04533            }
 04534            ConstrainSubtypeRelation(lineType, e1.Type, err);
 04535            var step = (s.StepOps[i - 1] ?? s.Op).StepExpr(e0, e1); // Use custom line operator
 04536            ResolveExpression(step, resolutionContext);
 04537            s.Steps.Add(step);
 04538            e0 = e1;
 04539          }
 4540
 4541          // clear the labels for the duration of checking the hints, because break statements are not allowed to leave 
 04542          var prevLblStmts = enclosingStatementLabels;
 04543          var prevLoopStack = loopStack;
 04544          enclosingStatementLabels = new Scope<Statement>(Options);
 04545          loopStack = new List<Statement>();
 04546          foreach (var h in s.Hints) {
 04547            foreach (var oneHint in h.Body) {
 04548              DominatingStatementLabels.PushMarker();
 04549              ResolveStatement(oneHint, resolutionContext);
 04550              DominatingStatementLabels.PopMarker();
 04551            }
 04552          }
 04553          enclosingStatementLabels = prevLblStmts;
 04554          loopStack = prevLoopStack;
 4555
 04556        }
 04557        if (prevErrorCount == reporter.Count(ErrorLevel.Error) && s.Lines.Count > 0) {
 4558          // do not build Result from the lines if there were errors, as it might be ill-typed and produce unnecessary r
 04559          var resultOp = s.StepOps.Aggregate(s.Op, (op0, op1) => op1 == null ? op0 : op0.ResultOp(op1));
 04560          s.Result = resultOp.StepExpr(s.Lines.First(), s.Lines.Last());
 04561        } else {
 04562          s.Result = CalcStmt.DefaultOp.StepExpr(Expression.CreateIntLiteral(s.Tok, 0), Expression.CreateIntLiteral(s.To
 04563        }
 04564        ResolveExpression(s.Result, resolutionContext);
 04565        Contract.Assert(s.Result != null);
 04566        Contract.Assert(prevErrorCount != reporter.Count(ErrorLevel.Error) || s.Steps.Count == s.Hints.Count);
 4567
 04568      } else if (stmt is SkeletonStatement) {
 04569        var s = (SkeletonStatement)stmt;
 04570        reporter.Error(MessageSource.Resolver, s.Tok, "skeleton statements are allowed only in refining methods");
 4571        // nevertheless, resolve the underlying statement; hey, why not
 04572        if (s.S != null) {
 04573          ResolveStatement(s.S, resolutionContext);
 04574        }
 04575      } else {
 04576        Contract.Assert(false); throw new cce.UnreachableException();
 4577      }
 2544664578    }
 4579
 4580    private void ResolveLoopSpecificationComponents(List<AttributedExpression> invariants, Specification<Expression> dec
 14824581      Specification<FrameExpression> modifies, ResolutionContext resolutionContext) {
 4582      Contract.Requires(invariants != null);
 4583      Contract.Requires(decreases != null);
 4584      Contract.Requires(modifies != null);
 4585      Contract.Requires(resolutionContext != null);
 4586
 88924587      foreach (AttributedExpression inv in invariants) {
 14824588        ResolveAttributes(inv, resolutionContext);
 14824589        ResolveExpression(inv.E, resolutionContext);
 14824590        Contract.Assert(inv.E.Type != null);  // follows from postcondition of ResolveExpression
 14824591        ConstrainTypeExprBool(inv.E, "invariant is expected to be of type bool, but is {0}");
 14824592      }
 4593
 14824594      ResolveAttributes(decreases, resolutionContext);
 67564595      foreach (Expression e in decreases.Expressions) {
 7704596        ResolveExpression(e, resolutionContext);
 7704597        if (e is WildcardExpr && !resolutionContext.CodeContext.AllowsNontermination) {
 04598          reporter.Error(MessageSource.Resolver, e, "a possibly infinite loop is allowed only if the enclosing method is
 04599        }
 4600        // any type is fine
 7704601      }
 4602
 14824603      ResolveAttributes(modifies, resolutionContext);
 14824604      if (modifies.Expressions != null) {
 04605        foreach (FrameExpression fe in modifies.Expressions) {
 04606          ResolveFrameExpression(fe, FrameExpressionUse.Modifies, resolutionContext);
 04607        }
 04608      }
 14824609    }
 4610
 4611    /// <summary>
 4612    /// Resolves the default-valued expression for each formal in "formals".
 4613    /// Solves the resulting type constraints.
 4614    /// Assumes these are the only type constraints to be solved.
 4615    ///
 4616    /// Reports an error for any cyclic dependency among the default-value expressions of the formals.
 4617    /// </summary>
 62434618    public void ResolveParameterDefaultValues(List<Formal> formals, ResolutionContext resolutionContext) {
 4619      Contract.Requires(formals != null);
 4620      Contract.Requires(resolutionContext != null);
 4621
 62434622      Contract.Assume(AllTypeConstraints.Count == 0);
 4623
 4624      // Formal parameters have three ways to indicate how they are to be passed in:
 4625      //   * nameonly: the only way to give a specific argument value is to name the parameter
 4626      //   * positional only: these are nameless parameters (which are allowed only for datatype constructor parameters)
 4627      //   * either positional or by name: this is the most common parameter
 4628      // A parameter is either required or optional:
 4629      //   * required: a caller has to supply an argument
 4630      //   * optional: the parameter has a default value that is used if a caller omits passing a specific argument
 4631      //
 4632      // The syntax for giving a positional-only (i.e., nameless) parameter does not allow a default-value expression, s
 4633      // a positional-only parameter is always required.
 4634      //
 4635      // At a call site, positional arguments are not allowed to follow named arguments. Therefore, if "x" is
 4636      // a nameonly parameter, then there is no way to supply the parameters after "x" by position. Thus, any
 4637      // parameter that follows "x" must either be passed by name or have a default value. That is, if a later
 4638      // parameter does not have a default value, it is _effectively_ nameonly. We impose the rule that
 4639      //   * an effectively nameonly parameter must be declared as nameonly
 4640      //
 4641      // For a positional-only parameter "x", every parameter preceding "x" is _effectively_ required. We impose
 4642      // the rule that
 4643      //   * an effectively required parameter must not have a default-value expression
 62434644      var dependencies = new Graph<IVariable>();
 62434645      string nameOfMostRecentNameonlyParameter = null;
 62434646      var previousParametersWithDefaultValue = new HashSet<Formal>();
 538864647      foreach (var formal in formals) {
 117194648        if (!formal.HasName) {
 04649          foreach (var previousFormal in previousParametersWithDefaultValue) {
 04650            reporter.Error(MessageSource.Resolver, previousFormal.DefaultValue.tok,
 04651              $"because of a later nameless parameter, this default value is never used; remove it or name all subsequen
 04652          }
 04653          previousParametersWithDefaultValue.Clear();
 04654        }
 117194655        var d = formal.DefaultValue;
 117194656        if (d != null) {
 04657          ResolveExpression(d, resolutionContext);
 04658          AddAssignableConstraint(d.tok, formal.Type, d.Type, "default-value expression (of type '{1}') is not assignabl
 04659          foreach (var v in FreeVariables(d)) {
 04660            dependencies.AddEdge(formal, v);
 04661          }
 04662          previousParametersWithDefaultValue.Add(formal);
 117194663        } else if (nameOfMostRecentNameonlyParameter != null && !formal.IsNameOnly) {
 4664          // "formal" is preceded by a nameonly parameter, but itself is neither nameonly nor has a default value
 04665          reporter.Error(MessageSource.Resolver, formal.tok,
 04666            $"this parameter is effectively nameonly (because of the earlier nameonly parameter '{nameOfMostRecentNameon
 04667            "declare it as nameonly or give it a default-value expression");
 04668        }
 117194669        if (formal.IsNameOnly) {
 04670          nameOfMostRecentNameonlyParameter = formal.Name;
 04671        }
 117194672      }
 62434673      SolveAllTypeConstraints();
 4674
 187294675      foreach (var cycle in dependencies.AllCycles()) {
 04676        var cy = Util.Comma(" -> ", cycle, v => v.Name) + " -> " + cycle[0].Name;
 04677        reporter.Error(MessageSource.Resolver, cycle[0], $"default-value expressions for parameters contain a cycle: {cy
 04678      }
 62434679    }
 4680
 4681    /// <summary>
 4682    /// See ResolveTypeOption for a description of the option/defaultTypeArguments parameters.
 4683    /// </summary>
 2852694684    public void ResolveType(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeOptionEnum eopt, List
 4685      Contract.Requires(tok != null);
 4686      Contract.Requires(type != null);
 4687      Contract.Requires(resolutionContext != null);
 4688      Contract.Requires(eopt != ResolveTypeOptionEnum.AllowPrefixExtend);
 2852694689      ResolveType(tok, type, resolutionContext, new ResolveTypeOption(eopt), defaultTypeArguments);
 2852694690    }
 4691
 14324692    public void ResolveType(IToken tok, Type type, ICodeContext topLevelContext, ResolveTypeOptionEnum eopt, List<TypePa
 14324693      ResolveType(tok, type, ResolutionContext.FromCodeContext(topLevelContext), eopt, defaultTypeArguments);
 14324694    }
 4695
 181554696    public void ResolveType(IToken tok, Type type, ICodeContext topLevelContext, ResolveTypeOption option, List<TypePara
 181554697      ResolveType(tok, type, ResolutionContext.FromCodeContext(topLevelContext), option, defaultTypeArguments);
 181554698    }
 4699
 4432734700    public void ResolveType(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeOption option, List<T
 4701      Contract.Requires(tok != null);
 4702      Contract.Requires(type != null);
 4703      Contract.Requires(resolutionContext != null);
 4704      Contract.Requires(option != null);
 4705      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 4432734706      var r = ResolveTypeLenient(tok, type, resolutionContext, option, defaultTypeArguments, false);
 4432734707      Contract.Assert(r == null);
 4432734708    }
 4709
 4710    public class ResolveTypeReturn {
 4711      public readonly Type ReplacementType;
 4712      public readonly ExprDotName LastComponent;
 04713      public ResolveTypeReturn(Type replacementType, ExprDotName lastComponent) {
 4714        Contract.Requires(replacementType != null);
 4715        Contract.Requires(lastComponent != null);
 04716        ReplacementType = replacementType;
 04717        LastComponent = lastComponent;
 04718      }
 4719    }
 4720    /// <summary>
 4721    /// See ResolveTypeOption for a description of the option/defaultTypeArguments parameters.
 4722    /// One more thing:  if "allowDanglingDotName" is true, then if the resolution would have produced
 4723    ///   an error message that could have been avoided if "type" denoted an identifier sequence one
 4724    ///   shorter, then return an unresolved replacement type where the identifier sequence is one
 4725    ///   shorter.  (In all other cases, the method returns null.)
 4726    /// </summary>
 4432734727    public ResolveTypeReturn ResolveTypeLenient(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeO
 4728      Contract.Requires(tok != null);
 4729      Contract.Requires(type != null);
 4730      Contract.Requires(resolutionContext != null);
 4731      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 4432734732      if (type is BitvectorType) {
 04733        var t = (BitvectorType)type;
 4734        // nothing to resolve, but record the fact that this bitvector width is in use
 04735        builtIns.Bitwidths.Add(t.Width);
 6186304736      } else if (type is BasicType) {
 4737        // nothing to resolve
 4561534738      } else if (type is MapType) {
 128804739        var mt = (MapType)type;
 128804740        var errorCount = reporter.Count(ErrorLevel.Error);
 4741        int typeArgumentCount;
 257604742        if (mt.HasTypeArg()) {
 128804743          ResolveType(tok, mt.Domain, resolutionContext, option, defaultTypeArguments);
 128804744          ResolveType(tok, mt.Range, resolutionContext, option, defaultTypeArguments);
 128804745          typeArgumentCount = 2;
 128804746        } else if (option.Opt == ResolveTypeOptionEnum.DontInfer) {
 04747          mt.SetTypeArgs(new InferredTypeProxy(), new InferredTypeProxy());
 04748          typeArgumentCount = 0;
 04749        } else {
 04750          var inferredTypeArgs = new List<Type>();
 04751          FillInTypeArguments(tok, 2, inferredTypeArgs, defaultTypeArguments, option);
 04752          Contract.Assert(inferredTypeArgs.Count <= 2);
 04753          if (inferredTypeArgs.Count == 1) {
 04754            mt.SetTypeArgs(inferredTypeArgs[0], new InferredTypeProxy());
 04755            typeArgumentCount = 1;
 04756          } else if (inferredTypeArgs.Count == 2) {
 04757            mt.SetTypeArgs(inferredTypeArgs[0], inferredTypeArgs[1]);
 04758            typeArgumentCount = 2;
 04759          } else {
 04760            mt.SetTypeArgs(new InferredTypeProxy(), new InferredTypeProxy());
 04761            typeArgumentCount = 0;
 04762          }
 04763        }
 4764        // defaults and auto have been applied; check if we now have the right number of arguments
 128804765        if (2 != typeArgumentCount) {
 04766          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of 2) passed to type:
 04767        }
 2983244768      } else if (type is CollectionType) {
 304084769        var t = (CollectionType)type;
 304084770        var errorCount = reporter.Count(ErrorLevel.Error);
 595924771        if (t.HasTypeArg()) {
 291844772          ResolveType(tok, t.Arg, resolutionContext, option, defaultTypeArguments);
 316324773        } else if (option.Opt != ResolveTypeOptionEnum.DontInfer) {
 12244774          var inferredTypeArgs = new List<Type>();
 12244775          FillInTypeArguments(tok, 1, inferredTypeArgs, defaultTypeArguments, option);
 24484776          if (inferredTypeArgs.Count != 0) {
 12244777            Contract.Assert(inferredTypeArgs.Count == 1);
 12244778            t.SetTypeArg(inferredTypeArgs[0]);
 12244779          }
 12244780        }
 304084781        if (!t.HasTypeArg()) {
 4782          // defaults and auto have been applied; check if we now have the right number of arguments
 04783          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments (0 instead of 1) passed to type: {
 4784          // add a proxy type, to make sure that CollectionType will have have a non-null Arg
 04785          t.SetTypeArg(new InferredTypeProxy());
 04786        }
 4787
 4677884788      } else if (type is UserDefinedType) {
 2127524789        var t = (UserDefinedType)type;
 2133994790        if (t.ResolvedClass != null) {
 4791          // Apparently, this type has already been resolved
 6474792          return null;
 4793        }
 2121054794        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 2121054795        if (t.NamePath is ExprDotName) {
 04796          var ret = ResolveDotSuffix_Type((ExprDotName)t.NamePath, resolutionContext, allowDanglingDotName, option, defa
 04797          if (ret != null) {
 04798            return ret;
 4799          }
 2121054800        } else {
 2121054801          var s = (NameSegment)t.NamePath;
 2121054802          ResolveNameSegment_Type(s, resolutionContext, option, defaultTypeArguments);
 2121054803        }
 4242104804        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2121054805          var r = t.NamePath.Resolved as Resolver_IdentifierExpr;
 2121054806          if (r == null || !(r.Type is Resolver_IdentifierExpr.ResolverType_Type)) {
 04807            reporter.Error(MessageSource.Resolver, t.tok, "expected type");
 4242104808          } else if (r.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 2121054809            var d = r.Decl;
 2121054810            if (d is AbstractTypeDecl) {
 4811              // resolve like a type parameter, and it may have type parameters if it's an abstract type
 04812              t.ResolvedClass = d;  // Store the decl, so the compiler will generate the fully qualified name
 3843454813            } else if (d is RedirectingTypeDecl) {
 1722404814              var dd = (RedirectingTypeDecl)d;
 1722404815              var caller = CodeContextWrapper.Unwrap(resolutionContext.CodeContext) as ICallable;
 3438684816              if (caller != null && !(d is SubsetTypeDecl && caller is SpecialFunction)) {
 3432564817                if (caller != d) {
 1716284818                } else if (d is TypeSynonymDecl && !(d is SubsetTypeDecl)) {
 4819                  // detect self-loops here, since they don't show up in the graph's SCC methods
 04820                  reporter.Error(MessageSource.Resolver, d.tok, "type-synonym cycle: {0} -> {0}", d.Name);
 04821                } else {
 4822                  // detect self-loops here, since they don't show up in the graph's SCC methods
 04823                  reporter.Error(MessageSource.Resolver, d.tok, "recursive constraint dependency involving a {0}: {1} ->
 04824                }
 1716284825              }
 1722404826              t.ResolvedClass = d;
 2473854827            } else if (d is DatatypeDecl) {
 352804828              t.ResolvedClass = d;
 398654829            } else {
 4830              // d is a type parameter, coinductive datatype, or class, and it may have type parameters
 45854831              t.ResolvedClass = d;
 45854832            }
 3779304833            if (option.Opt == ResolveTypeOptionEnum.DontInfer) {
 4834              // don't add anything
 2121054835            } else if (d.TypeArgs.Count != t.TypeArgs.Count && t.TypeArgs.Count == 0) {
 04836              FillInTypeArguments(t.tok, d.TypeArgs.Count, t.TypeArgs, defaultTypeArguments, option);
 04837            }
 4838            // defaults and auto have been applied; check if we now have the right number of arguments
 2121054839            if (d.TypeArgs.Count != t.TypeArgs.Count) {
 04840              reporter.Error(MessageSource.Resolver, t.tok, "Wrong number of type arguments ({0} instead of {1}) passed 
 04841            }
 4842
 2121054843          }
 2121054844        }
 2121054845        if (t.ResolvedClass == null) {
 4846          // There was some error. Still, we will set .ResolvedClass to some value to prevent some crashes in the downst
 4847          // 0-tuple is convenient, because it is always in scope.
 04848          t.ResolvedClass = builtIns.TupleType(t.tok, 0, false);
 4849          // clear out the TypeArgs since 0-tuple doesn't take TypeArg
 04850          t.TypeArgs = new List<Type>();
 04851        }
 4852
 2352454853      } else if (type is TypeProxy) {
 112644854        TypeProxy t = (TypeProxy)type;
 112644855        if (t.T != null) {
 04856          ResolveType(tok, t.T, resolutionContext, option, defaultTypeArguments);
 04857        }
 124884858      } else if (type is SelfType) {
 4859        // do nothing.
 6124860      } else {
 04861        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4862      }
 4426264863      return null;
 4432734864    }
 4865
 4866    /// <summary>
 4867    /// Adds to "typeArgs" a list of "n" type arguments, possibly extending "defaultTypeArguments".
 4868    /// </summary>
 12244869    static void FillInTypeArguments(IToken tok, int n, List<Type> typeArgs, List<TypeParameter> defaultTypeArguments, Re
 4870      Contract.Requires(tok != null);
 4871      Contract.Requires(0 <= n);
 4872      Contract.Requires(typeArgs != null && typeArgs.Count == 0);
 18364873      if (option.Opt == ResolveTypeOptionEnum.InferTypeProxies) {
 4874        // add type arguments that will be inferred
 30604875        for (int i = 0; i < n; i++) {
 6124876          typeArgs.Add(new InferredTypeProxy());
 6124877        }
 12244878      } else if (option.Opt == ResolveTypeOptionEnum.AllowPrefix && defaultTypeArguments.Count < n) {
 4879        // there aren't enough default arguments, so don't do anything
 6124880      } else {
 4881        // we'll add arguments
 12244882        if (option.Opt == ResolveTypeOptionEnum.AllowPrefixExtend) {
 4883          // extend defaultTypeArguments, if needed
 30604884          for (int i = defaultTypeArguments.Count; i < n; i++) {
 6124885            var tp = new TypeParameter(tok.ToRange(), new Name(tok.ToRange(), "_T" + i), i, option.Parent);
 6124886            if (option.Parent is IteratorDecl) {
 04887              tp.Characteristics.AutoInit = Type.AutoInitInfo.CompilableValue;
 04888            }
 6124889            defaultTypeArguments.Add(tp);
 6124890          }
 6124891        }
 6124892        Contract.Assert(n <= defaultTypeArguments.Count);
 4893        // automatically supply a prefix of the arguments from defaultTypeArguments
 30604894        for (int i = 0; i < n; i++) {
 6124895          typeArgs.Add(new UserDefinedType(defaultTypeArguments[i]));
 6124896        }
 6124897      }
 12244898    }
 4899
 16484900    public static bool TypeConstraintsIncludeProxy(Type t, TypeProxy proxy) {
 16484901      return TypeConstraintsIncludeProxy_Aux(t, proxy, new HashSet<TypeProxy>());
 16484902    }
 24384903    static bool TypeConstraintsIncludeProxy_Aux(Type t, TypeProxy proxy, ISet<TypeProxy> visited) {
 4904      Contract.Requires(t != null);
 4905      Contract.Requires(!(t is TypeProxy) || ((TypeProxy)t).T == null);  // t is expected to have been normalized first
 4906      Contract.Requires(proxy != null && proxy.T == null);
 4907      Contract.Requires(visited != null);
 24384908      var tproxy = t as TypeProxy;
 24384909      if (tproxy != null) {
 04910        if (object.ReferenceEquals(tproxy, proxy)) {
 04911          return true;
 04912        } else if (visited.Contains(tproxy)) {
 04913          return false;
 4914        }
 04915        visited.Add(tproxy);
 04916        foreach (var su in tproxy.Subtypes) {
 04917          if (TypeConstraintsIncludeProxy_Aux(su, proxy, visited)) {
 04918            return true;
 4919          }
 04920        }
 04921        foreach (var su in tproxy.Supertypes) {
 04922          if (TypeConstraintsIncludeProxy_Aux(su, proxy, visited)) {
 04923            return true;
 4924          }
 04925        }
 24384926      } else {
 4927        // check type arguments of t
 96844928        foreach (var ta in t.TypeArgs) {
 7904929          var a = ta.Normalize();
 7904930          if (TypeConstraintsIncludeProxy_Aux(a, proxy, visited)) {
 04931            return true;
 4932          }
 7904933        }
 24384934      }
 24384935      return false;
 24384936    }
 4937
 122984938    public Type ResolveTypeRhs(TypeRhs rr, Statement stmt, ResolutionContext resolutionContext) {
 4939      Contract.Requires(rr != null);
 4940      Contract.Requires(stmt != null);
 4941      Contract.Requires(resolutionContext != null);
 4942      Contract.Ensures(Contract.Result<Type>() != null);
 4943
 184474944      if (rr.Type == null) {
 122984945        if (rr.ArrayDimensions != null) {
 4946          // ---------- new T[EE]    OR    new T[EE] (elementInit)
 61494947          Contract.Assert(rr.Bindings == null && rr.Path == null && rr.InitCall == null);
 61494948          ResolveType(stmt.Tok, rr.EType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 61494949          int i = 0;
 368944950          foreach (Expression dim in rr.ArrayDimensions) {
 61494951            Contract.Assert(dim != null);
 61494952            ResolveExpression(dim, resolutionContext);
 61494953            ConstrainToIntegerType(dim, false, string.Format("new must use an integer-based expression for the array siz
 61494954            i++;
 61494955          }
 61494956          rr.Type = ResolvedArrayType(stmt.Tok, rr.ArrayDimensions.Count, rr.EType, resolutionContext, false);
 61494957          if (rr.ElementInit != null) {
 04958            ResolveExpression(rr.ElementInit, resolutionContext);
 4959            // Check
 4960            //     int^N -> rr.EType  :>  rr.ElementInit.Type
 04961            builtIns.CreateArrowTypeDecl(rr.ArrayDimensions.Count);  // TODO: should this be done already in the parser?
 04962            var args = new List<Type>();
 04963            for (int ii = 0; ii < rr.ArrayDimensions.Count; ii++) {
 04964              args.Add(builtIns.Nat());
 04965            }
 04966            var arrowType = new ArrowType(rr.ElementInit.tok, builtIns.ArrowTypeDecls[rr.ArrayDimensions.Count], args, r
 04967            var lambdaType = rr.ElementInit.Type.AsArrowType;
 04968            if (lambdaType != null && lambdaType.TypeArgs[0] is InferredTypeProxy) {
 04969              (lambdaType.TypeArgs[0] as InferredTypeProxy).KeepConstraints = true;
 04970            }
 4971            string underscores;
 04972            if (rr.ArrayDimensions.Count == 1) {
 04973              underscores = "_";
 04974            } else {
 04975              underscores = "(" + Util.Comma(rr.ArrayDimensions.Count, x => "_") + ")";
 04976            }
 04977            var hintString = string.Format(" (perhaps write '{0} =>' in front of the expression you gave in order to mak
 04978            ConstrainSubtypeRelation(arrowType, rr.ElementInit.Type, rr.ElementInit, "array-allocation initialization ex
 04979              arrowType, rr.ElementInit.Type, new LazyString_OnTypeEquals(rr.EType, rr.ElementInit.Type, hintString));
 116484980          } else if (rr.InitDisplay != null) {
 824824981            foreach (var v in rr.InitDisplay) {
 219954982              ResolveExpression(v, resolutionContext);
 219954983              AddAssignableConstraint(v.tok, rr.EType, v.Type, "initial value must be assignable to array's elements (ex
 219954984            }
 54994985          }
 61494986        } else {
 04987          bool callsConstructor = false;
 04988          if (rr.Bindings == null) {
 04989            ResolveType(stmt.Tok, rr.EType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04990            var cl = (rr.EType as UserDefinedType)?.ResolvedClass as NonNullTypeDecl;
 04991            if (cl != null && !(rr.EType.IsTraitType && !rr.EType.NormalizeExpand().IsObjectQ)) {
 4992              // life is good
 04993            } else {
 04994              reporter.Error(MessageSource.Resolver, rr.tok, "new can be applied only to class types (got {0})", rr.ETyp
 04995            }
 04996          } else {
 04997            string initCallName = null;
 04998            IToken initCallTok = null;
 4999            // Resolve rr.Path and do one of three things:
 5000            // * If rr.Path denotes a type, then set EType,initCallName to rr.Path,"_ctor", which sets up a call to the 
 5001            // * If the all-but-last components of rr.Path denote a type, then do EType,initCallName := allButLast(EType
 5002            // * Otherwise, report an error
 05003            var ret = ResolveTypeLenient(rr.Tok, rr.Path, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum
 05004            if (ret != null) {
 5005              // The all-but-last components of rr.Path denote a type (namely, ret.ReplacementType).
 05006              rr.EType = ret.ReplacementType;
 05007              initCallName = ret.LastComponent.SuffixName;
 05008              initCallTok = ret.LastComponent.tok;
 05009            } else {
 5010              // Either rr.Path resolved correctly as a type or there was no way to drop a last component to make it int
 5011              // like a type.  In either case, set EType,initCallName to Path,"_ctor" and continue.
 05012              rr.EType = rr.Path;
 05013              initCallName = "_ctor";
 05014              initCallTok = rr.Tok;
 05015            }
 05016            var cl = (rr.EType as UserDefinedType)?.ResolvedClass as NonNullTypeDecl;
 05017            if (cl == null || rr.EType.IsTraitType) {
 05018              reporter.Error(MessageSource.Resolver, rr.tok, "new can be applied only to class types (got {0})", rr.ETyp
 05019            } else {
 5020              // ---------- new C.Init(EE)
 05021              Contract.Assert(initCallName != null);
 05022              var prevErrorCount = reporter.Count(ErrorLevel.Error);
 5023
 5024              // We want to create a MemberSelectExpr for the initializing method.  To do that, we create a throw-away r
 5025              // type, create a dot-suffix expression around this receiver, and then resolve it in the usual way for dot
 05026              var lhs = new ImplicitThisExpr_ConstructorCall(initCallTok) { Type = rr.EType };
 05027              var callLhs = new ExprDotName(((UserDefinedType)rr.EType).tok, lhs, initCallName, ret == null ? null : ret
 05028              ResolveDotSuffix(callLhs, true, rr.Bindings.ArgumentBindings, resolutionContext, true);
 05029              if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 05030                Contract.Assert(callLhs.ResolvedExpression is MemberSelectExpr);  // since ResolveApplySuffix succeeded 
 05031                var methodSel = (MemberSelectExpr)callLhs.ResolvedExpression;
 05032                if (methodSel.Member is Method) {
 05033                  rr.InitCall = new CallStmt(stmt.RangeToken, new List<Expression>(), methodSel, rr.Bindings.ArgumentBin
 05034                  ResolveCallStmt(rr.InitCall, resolutionContext, rr.EType);
 05035                  if (rr.InitCall.Method is Constructor) {
 05036                    callsConstructor = true;
 05037                  }
 05038                } else {
 05039                  reporter.Error(MessageSource.Resolver, initCallTok, "object initialization must denote an initializing
 05040                }
 05041              }
 05042            }
 05043          }
 05044          if (rr.EType.IsRefType) {
 05045            var udt = rr.EType.NormalizeExpand() as UserDefinedType;
 05046            if (udt != null) {
 05047              var cl = (ClassDecl)udt.ResolvedClass;  // cast is guaranteed by the call to rr.EType.IsRefType above, tog
 05048              if (!callsConstructor && !cl.IsObjectTrait && !udt.IsArrayType && (cl.HasConstructor || cl.EnclosingModule
 05049                reporter.Error(MessageSource.Resolver, stmt, "when allocating an object of {1}type '{0}', one of its con
 05050                  cl.HasConstructor ? "" : "imported ");
 05051              }
 05052            }
 05053          }
 05054          rr.Type = rr.EType;
 05055        }
 61495056      }
 122985057      return rr.Type;
 122985058    }
 5059
 5060    /// <summary>
 5061    /// Resolve "memberName" in what currently is known as "receiverType". If "receiverType" is an unresolved
 5062    /// proxy type, try to solve enough type constraints and use heuristics to figure out which type contains
 5063    /// "memberName" and return that enclosing type as "tentativeReceiverType". However, try not to make
 5064    /// type-inference decisions about "receiverType"; instead, lay down the further constraints that need to
 5065    /// be satisfied in order for "tentativeReceiverType" to be where "memberName" is found.
 5066    /// Consequently, if "memberName" is found and returned as a "MemberDecl", it may still be the case that
 5067    /// "receiverType" is an unresolved proxy type and that, after solving more type constraints, "receiverType"
 5068    /// eventually gets set to a type more specific than "tentativeReceiverType".
 5069    /// </summary>
 160295070    public MemberDecl ResolveMember(IToken tok, Type receiverType, string memberName, out NonProxyType tentativeReceiver
 5071      Contract.Requires(tok != null);
 5072      Contract.Requires(receiverType != null);
 5073      Contract.Requires(memberName != null);
 5074      Contract.Ensures(Contract.Result<MemberDecl>() == null || Contract.ValueAtReturn(out tentativeReceiverType) != nul
 5075
 160295076      receiverType = PartiallyResolveTypeForMemberSelection(tok, receiverType, memberName);
 5077
 160295078      if (receiverType is TypeProxy) {
 05079        reporter.Error(MessageSource.Resolver, tok, "type of the receiver is not fully determined at this program point"
 05080        tentativeReceiverType = null;
 05081        return null;
 5082      }
 160295083      Contract.Assert(receiverType is NonProxyType);  // there are only two kinds of types: proxies and non-proxies
 5084
 3784065085      foreach (var valuet in valuetypeDecls) {
 1108535086        if (valuet.IsThisType(receiverType)) {
 11205087          if (valuet.Members.TryGetValue(memberName, out var member)) {
 5605088            SelfType resultType = null;
 5605089            if (member is SpecialFunction) {
 05090              resultType = ((SpecialFunction)member).ResultType as SelfType;
 11205091            } else if (member is SpecialField) {
 5605092              resultType = ((SpecialField)member).Type as SelfType;
 5605093            }
 5605094            if (resultType != null) {
 05095              SelfTypeSubstitution = new Dictionary<TypeParameter, Type>();
 05096              SelfTypeSubstitution.Add(resultType.TypeArg, receiverType);
 05097              resultType.ResolvedType = receiverType;
 05098            }
 5605099            tentativeReceiverType = (NonProxyType)receiverType;
 5605100            return member;
 5101          }
 05102          break;
 5103        }
 1097335104      }
 5105
 154695106      var ctype = receiverType.NormalizeExpand() as UserDefinedType;
 154695107      var cd = ctype?.AsTopLevelTypeWithMembersBypassInternalSynonym;
 309385108      if (cd != null) {
 154695109        Contract.Assert(ctype.TypeArgs.Count == cd.TypeArgs.Count);  // follows from the fact that ctype was resolved
 154695110        if (!classMembers[cd].TryGetValue(memberName, out var member)) {
 05111          if (memberName == "_ctor") {
 05112            reporter.Error(MessageSource.Resolver, tok, "{0} {1} does not have an anonymous constructor", cd.WhatKind, c
 05113          } else {
 05114            reporter.Error(MessageSource.Resolver, tok, "member '{0}' does not exist in {2} '{1}'", memberName, cd.Name,
 05115          }
 154695116        } else if (!VisibleInScope(member)) {
 05117          reporter.Error(MessageSource.Resolver, tok, "member '{0}' has not been imported in this scope and cannot be ac
 154695118        } else {
 154695119          tentativeReceiverType = ctype;
 154695120          return member;
 5121        }
 05122        tentativeReceiverType = null;
 05123        return null;
 5124      }
 5125
 05126      reporter.Error(MessageSource.Resolver, tok, "type {0} does not have a member {1}", receiverType, memberName);
 05127      tentativeReceiverType = null;
 05128      return null;
 160295129    }
 5130
 5131    /// <summary>
 5132    /// Roughly speaking, tries to figure out the head of the type of "t", making as few inference decisions as possible
 5133    /// More precisely, returns a type that contains all the members of "t"; or if "memberName" is non-null, a type
 5134    /// that at least contains the member "memberName" of "t".  Typically, this type is the head type of "t",
 5135    /// but it may also be a type in a super- or subtype relation to "t".
 5136    /// In some cases, it is necessary to make some inference decisions in order to figure out the type to return.
 5137    /// </summary>
 978305138    public Type PartiallyResolveTypeForMemberSelection(IToken tok, Type t, string memberName = null, int strength = 0) {
 5139      Contract.Requires(tok != null);
 5140      Contract.Requires(t != null);
 5141      Contract.Ensures(Contract.Result<Type>() != null);
 5142      Contract.Ensures(!(Contract.Result<Type>() is TypeProxy) || ((TypeProxy)Contract.Result<Type>()).T == null);
 978305143      t = t.NormalizeExpand();
 1542065144      if (!(t is TypeProxy)) {
 563765145        return t;  // we're good
 5146      }
 5147
 5148      // simplify constraints
 414545149      PrintTypeConstraintState(10);
 563165150      if (strength > 0) {
 148625151        var proxySpecializations = new HashSet<TypeProxy>();
 148625152        GetRelatedTypeProxies(t, proxySpecializations);
 148625153        var anyNewConstraintsAssignable = ConvertAssignableToSubtypeConstraints(proxySpecializations);
 148625154        var anyNewConstraintsEquatable = TightenUpEquatable(proxySpecializations);
 222935155        if ((strength > 1 && !anyNewConstraintsAssignable && !anyNewConstraintsEquatable) || strength == 10) {
 148625156          if (t is TypeProxy) {
 5157            // One more try
 74315158            var r = GetBaseTypeFromProxy((TypeProxy)t, new Dictionary<TypeProxy, Type>());
 74315159            if (r != null) {
 05160              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05161                Options.OutputWriter.WriteLine("  ----> found improvement through GetBaseTypeFromProxy: {0}", r);
 05162              }
 05163              return r;
 5164            }
 74315165          }
 5166
 74315167          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05168            Options.OutputWriter.WriteLine("  ----> found no improvement, giving up");
 05169          }
 74315170          return t;
 5171        }
 74315172      }
 340235173      PartiallySolveTypeConstraints(false);
 340235174      PrintTypeConstraintState(11);
 340235175      t = t.NormalizeExpandKeepConstraints();
 340235176      var proxy = t as TypeProxy;
 345605177      if (proxy == null) {
 5375178        return t;  // simplification did the trick
 5179      }
 334865180      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05181        Options.OutputWriter.WriteLine("DEBUG: Member selection{3}:  {1} :> {0} :> {2}", t,
 05182          Util.Comma(proxy.SupertypesKeepConstraints, su => su.ToString()),
 05183          Util.Comma(proxy.SubtypesKeepConstraints, su => su.ToString()),
 05184          memberName == null ? "" : " (" + memberName + ")");
 05185      }
 5186
 5187      // Look for a join of head symbols among the proxy's subtypes
 334865188      Type joinType = null;
 338335189      if (JoinOfAllSubtypes(proxy, ref joinType, new HashSet<TypeProxy>()) && joinType != null) {
 3475190        DetermineRootLeaf(joinType, out _, out _, out var headIsRoot, out _);
 3475191        if (joinType.IsDatatype) {
 05192          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05193            Options.OutputWriter.WriteLine("  ----> join is a datatype: {0}", joinType);
 05194          }
 05195          ConstrainSubtypeRelation(t, joinType, tok, "Member selection requires a supertype of {0} (got something more l
 05196          return joinType;
 4925197        } else if (headIsRoot) {
 5198          // we're good to go -- by picking "join" (whose type parameters have been replaced by fresh proxies), we're no
 1455199          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05200            Options.OutputWriter.WriteLine("  ----> improved to {0} through join", joinType);
 05201          }
 1455202          AssignProxyAndHandleItsConstraints(proxy, joinType, true);
 1455203          return proxy.NormalizeExpand();  // we return proxy.T instead of join, in case the assignment gets hijacked
 2025204        } else if (memberName == "_#apply" || memberName == "requires" || memberName == "reads") {
 05205          var generalArrowType = joinType.AsArrowType;  // go all the way to the base type, to get to the general arrow 
 05206          if (generalArrowType != null) {
 5207            // pick the supertype "generalArrowType" of "join"
 05208            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05209              Options.OutputWriter.WriteLine("  ----> improved to {0} through join and function application", generalArr
 05210            }
 05211            ConstrainSubtypeRelation(generalArrowType, t, tok, "Function application requires a subtype of {0} (got some
 05212            return generalArrowType;
 5213          }
 4045214        } else if (memberName != null) {
 5215          // If "join" has a member called "memberName" and no supertype of "join" does, then we'll pick this join
 4045216          if (joinType.IsRefType) {
 2025217            var joinExpanded = joinType.NormalizeExpand();  // go all the way to the base type, to get to the class
 4045218            if (!joinExpanded.IsObjectQ) {
 2025219              var cl = ((UserDefinedType)joinExpanded).ResolvedClass as ClassDecl;
 4045220              if (cl != null) {
 5221                // TODO: the following could be improved by also supplying an upper bound of the search (computed as a j
 2025222                var plausibleMembers = new HashSet<MemberDecl>();
 2025223                FindAllMembers(cl, memberName, plausibleMembers);
 4045224                if (plausibleMembers.Count == 1) {
 2025225                  var mbr = plausibleMembers.First();
 4045226                  if (mbr.EnclosingClass == cl) {
 2025227                    if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05228                      Options.OutputWriter.WriteLine("  ----> improved to {0} through member-selection join", joinType);
 05229                    }
 2025230                    var joinRoot = joinType.NormalizeExpand();  // blow passed any constraints
 2025231                    ConstrainSubtypeRelation(joinRoot, t, tok, "Member selection requires a subtype of {0} (got somethin
 2025232                    return joinType;
 05233                  } else {
 5234                    // pick the supertype "mbr.EnclosingClass" of "cl"
 05235                    Contract.Assert(mbr.EnclosingClass is TraitDecl);  // a proper supertype of a ClassDecl must be a Tr
 05236                    var typeMapping = cl.ParentFormalTypeParametersToActuals;
 05237                    TopLevelDecl td = mbr.EnclosingClass;
 05238                    foreach (var tt in cl.TraitAncestors()) {
 5239                      // If there is a match, the list of Type actuals is unique
 5240                      // (a class cannot inherit both Trait<T1> and Trait<T2> with T1 != T2).
 05241                      if (tt == (TraitDecl)mbr.EnclosingClass) {
 05242                        td = tt;
 05243                      }
 05244                    }
 05245                    List<Type> proxyTypeArgs = td.TypeArgs.ConvertAll(t0 => typeMapping.ContainsKey(t0) ? typeMapping[t0
 05246                    var joinMapping = TypeParameter.SubstitutionMap(cl.TypeArgs, joinType.TypeArgs);
 05247                    proxyTypeArgs = proxyTypeArgs.ConvertAll(t0 => t0.Subst(joinMapping));
 05248                    proxyTypeArgs = proxyTypeArgs.ConvertAll(t0 => t0.AsTypeParameter == null ? t0 : (Type)new InferredT
 05249                    var pickItFromHere = new UserDefinedType(tok, mbr.EnclosingClass.Name, mbr.EnclosingClass, proxyType
 05250                    if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05251                      Options.OutputWriter.WriteLine("  ----> improved to {0} through join and member lookup", pickItFro
 05252                    }
 05253                    ConstrainSubtypeRelation(pickItFromHere, t, tok, "Member selection requires a subtype of {0} (got so
 05254                    return pickItFromHere;
 5255                  }
 5256                }
 05257              }
 05258            }
 05259          }
 05260        }
 05261        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05262          Options.OutputWriter.WriteLine("  ----> found no improvement, because join does not determine type enough");
 05263        }
 05264      }
 5265
 5266      // Compute the meet of the proxy's supertypes
 331395267      Type meet = null;
 510175268      if (MeetOfAllSupertypes(proxy, ref meet, new HashSet<TypeProxy>(), false) && meet != null) {
 5269        // If the meet does have the member, then this looks promising. It could be that the
 5270        // type would get further constrained later to pick some subtype (in particular, a
 5271        // subclass that overrides the member) of this meet. But this is the best we can do
 5272        // now.
 178785273        if (meet is TypeProxy) {
 05274          if (proxy == meet.Normalize()) {
 5275            // can this really ever happen?
 05276            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05277              Options.OutputWriter.WriteLine("  ----> found no improvement (other than the proxy itself)");
 05278            }
 05279            return t;
 05280          } else {
 05281            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05282              Options.OutputWriter.WriteLine("  ----> (merging, then trying to improve further) assigning proxy {0}.T :=
 05283            }
 05284            Contract.Assert(proxy != meet);
 05285            proxy.T = meet;
 05286            Contract.Assert(t.NormalizeExpand() == meet);
 05287            return PartiallyResolveTypeForMemberSelection(tok, t, memberName, strength + 1);
 5288          }
 5289        }
 178785290        if (!(meet is ArtificialType)) {
 05291          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05292            Options.OutputWriter.WriteLine("  ----> improved to {0} through meet", meet);
 05293          }
 05294          if (memberName != null) {
 05295            AssignProxyAndHandleItsConstraints(proxy, meet, true);
 05296            return proxy.NormalizeExpand(); // we return proxy.T instead of meet, in case the assignment gets hijacked
 05297          } else {
 05298            return meet;
 5299          }
 5300        }
 178785301      }
 5302
 5303      // as a last resort, act on any artificial type nearby the proxy
 331395304      var artificialSuper = proxy.InClusterOfArtificial(AllXConstraints);
 514165305      if (artificialSuper != null) {
 182775306        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05307          Options.OutputWriter.WriteLine("  ----> use artificial supertype: {0}", artificialSuper);
 05308        }
 182775309        return artificialSuper;
 5310      }
 5311
 5312      // we weren't able to do it
 148625313      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05314        Options.OutputWriter.WriteLine("  ----> found no improvement using simple things, trying harder once more");
 05315      }
 148625316      return PartiallyResolveTypeForMemberSelection(tok, t, memberName, strength + 1);
 978305317    }
 5318
 74315319    private Type/*?*/ GetBaseTypeFromProxy(TypeProxy proxy, Dictionary<TypeProxy, Type/*?*/> determinedProxies) {
 5320      Contract.Requires(proxy != null);
 5321      Contract.Requires(determinedProxies != null);
 74315322      if (determinedProxies.TryGetValue(proxy, out var t)) {
 5323        // "t" may be null (meaning search for "proxy" is underway or was unsuccessful) or non-null (search for
 5324        // "proxy" has completed successfully), but we return it in either case
 05325        return t;
 5326      }
 74315327      determinedProxies.Add(proxy, null);  // record that search for "proxy" is underway
 5328      // First, go through subtype constraints, treating each as if it were an equality
 35118155329      foreach (var c in AllTypeConstraints) {
 11631745330        t = GetBaseTypeFromProxy_Eq(proxy, c.Super, c.Sub, determinedProxies);
 11631745331        if (t != null) {
 05332          determinedProxies[proxy] = t;
 05333          return t;
 5334        }
 11631745335      }
 5336      // Next, check XConstraints that can be seen as equality constraints
 8895215337      foreach (var xc in AllXConstraints) {
 2890765338        switch (xc.ConstraintName) {
 5339          case "Assignable":
 5340          case "Equatable":
 5341          case "EquatableArg":
 1983365342            t = GetBaseTypeFromProxy_Eq(proxy, xc.Types[0], xc.Types[1], determinedProxies);
 1983365343            if (t != null) {
 05344              determinedProxies[proxy] = t;
 05345              return t;
 5346            }
 1983365347            break;
 5348          case "InSet":
 5349            // etc. TODO
 05350            break;
 5351          default:
 907405352            break;
 5353        }
 2890765354      }
 74315355      return null;
 74315356    }
 5357    /// <summary>
 5358    /// Tries to find a non-proxy type corresponding to "proxy", under the assumption that "t" equals "u" and
 5359    /// "determinedProxies" assumptions.  In the process, may add to "determinedProxies".
 5360    /// </summary>
 13615105361    private Type/*?*/ GetBaseTypeFromProxy_Eq(TypeProxy proxy, Type t, Type u, Dictionary<TypeProxy, Type/*?*/> determin
 5362      Contract.Requires(proxy != null);
 5363      Contract.Requires(determinedProxies != null);
 5364      Contract.Requires(t != null);
 5365      Contract.Requires(u != null);
 13615105366      t = t.NormalizeExpand();
 13615105367      u = u.NormalizeExpand();
 13615105368      return GetBaseTypeFromProxy_EqAux(proxy, t, u, determinedProxies) ?? GetBaseTypeFromProxy_EqAux(proxy, u, t, deter
 13615105369    }
 27230205370    private Type/*?*/ GetBaseTypeFromProxy_EqAux(TypeProxy proxy, Type t, Type u, Dictionary<TypeProxy, Type/*?*/> deter
 5371      Contract.Requires(proxy != null);
 5372      Contract.Requires(determinedProxies != null);
 5373      Contract.Requires(t != null && (!(t is TypeProxy) || ((TypeProxy)t).T == null));
 5374      Contract.Requires(u != null && (!(u is TypeProxy) || ((TypeProxy)u).T == null));
 27230205375      if (t == proxy) {
 05376        if (u is TypeProxy) {
 05377          return GetBaseTypeFromProxy((TypeProxy)u, determinedProxies);
 05378        } else {
 05379          return u;
 5380        }
 27230205381      } else if (t.ContainsProxy(proxy)) {
 05382        if (u is TypeProxy) {
 05383          u = GetBaseTypeFromProxy((TypeProxy)u, determinedProxies);
 05384          if (u == null) {
 05385            return null;
 5386          }
 05387        }
 05388        if (Type.SameHead(t, u)) {
 05389          Contract.Assert(t.TypeArgs.Count == u.TypeArgs.Count);
 05390          for (int i = 0; i < t.TypeArgs.Count; i++) {
 05391            var r = GetBaseTypeFromProxy_Eq(proxy, t.TypeArgs[i], u.TypeArgs[i], determinedProxies);
 05392            if (r != null) {
 05393              return r;
 5394            }
 05395          }
 05396        }
 05397      }
 27230205398      return null;
 27230205399    }
 5400
 148625401    private void GetRelatedTypeProxies(Type t, ISet<TypeProxy> proxies) {
 5402      Contract.Requires(t != null);
 5403      Contract.Requires(proxies != null);
 148625404      var proxy = t.Normalize() as TypeProxy;
 148625405      if (proxy == null || proxies.Contains(proxy)) {
 05406        return;
 5407      }
 148625408      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05409        Options.OutputWriter.WriteLine("DEBUG: GetRelatedTypeProxies: finding {0} interesting", proxy);
 05410      }
 148625411      proxies.Add(proxy);
 5412      // close over interesting constraints
 70236305413      foreach (var c in AllTypeConstraints) {
 23263485414        var super = c.Super.Normalize();
 23975065415        if (super.TypeArgs.Exists(ta => ta.Normalize() == proxy)) {
 05416          GetRelatedTypeProxies(c.Sub, proxies);
 05417        }
 23263485418      }
 17790425419      foreach (var xc in AllXConstraints) {
 5781525420        var xc0 = xc.Types[0].Normalize();
 5783345421        if (xc.ConstraintName == "Assignable" && (xc0 == proxy || xc0.TypeArgs.Exists(ta => ta.Normalize() == proxy))) {
 05422          GetRelatedTypeProxies(xc.Types[1], proxies);
 5781525423        } else if (xc.ConstraintName == "Innable" && xc.Types[1].Normalize() == proxy) {
 05424          GetRelatedTypeProxies(xc.Types[0], proxies);
 5781525425        } else if ((xc.ConstraintName == "ModifiesFrame" || xc.ConstraintName == "ReadsFrame") && xc.Types[1].Normalize(
 05426          GetRelatedTypeProxies(xc.Types[0], proxies);
 05427        }
 5781525428      }
 148625429    }
 5430
 5431    /// <summary>
 5432    /// Attempts to compute the join of "join", "t", and all of "t"'s known subtype( constraint)s.  The join
 5433    /// ignores type parameters.  It is assumed that "join" on entry already includes the join of all proxies
 5434    /// in "visited". The empty join is represented by "null".
 5435    /// The return is "true" if the join exists.
 5436    /// </summary>
 354935437    bool JoinOfAllSubtypes(Type t, ref Type joinType, ISet<TypeProxy> visited) {
 5438      Contract.Requires(t != null);
 5439      Contract.Requires(visited != null);
 5440
 354935441      t = t.NormalizeExpandKeepConstraints();
 5442
 354935443      var proxy = t as TypeProxy;
 700875444      if (proxy != null) {
 345945445        if (visited.Contains(proxy)) {
 05446          return true;
 5447        }
 345945448        visited.Add(proxy);
 5449
 1083335450        foreach (var c in proxy.SubtypeConstraints) {
 15175451          var s = c.Sub.NormalizeExpandKeepConstraints();
 15175452          if (!JoinOfAllSubtypes(s, ref joinType, visited)) {
 05453            return false;
 5454          }
 15175455        }
 684545456        if (joinType == null) {
 5457          // also consider "Assignable" constraints
 45278315458          foreach (var c in AllXConstraints) {
 14757075459            if (c.ConstraintName == "Assignable" && c.Types[0].Normalize() == proxy) {
 2905460              var s = c.Types[1].NormalizeExpandKeepConstraints();
 2905461              if (!JoinOfAllSubtypes(s, ref joinType, visited)) {
 05462                return false;
 5463              }
 2905464            }
 14754175465          }
 338605466        }
 345945467        return true;
 5468      }
 5469
 14465470      if (joinType == null) {
 5471        // stick with what we've got
 5475472        joinType = t;
 5475473        return true;
 6025474      } else if (Type.IsHeadSupertypeOf(joinType, t)) {
 5475        // stick with what we've got
 2505476        return true;
 2045477      } else if (Type.IsHeadSupertypeOf(t, joinType)) {
 1025478        joinType = Type.HeadWithProxyArgs(t);
 1025479        return true;
 05480      } else {
 05481        joinType = Type.Join(joinType, Type.HeadWithProxyArgs(t), builtIns);  // the only way this can succeed is if we 
 05482        Contract.Assert(joinType == null ||
 05483                        joinType.IsObjectQ || joinType.IsObject ||
 05484                        (joinType is UserDefinedType udt && (udt.ResolvedClass is TraitDecl || (udt.ResolvedClass is Non
 05485        return joinType != null;
 5486      }
 354935487    }
 5488
 5489    /// <summary>
 5490    /// Attempts to compute the meet of "meet", all of "t"'s known supertype( constraint)s, and, if "includeT"
 5491    /// and "t" has no supertype( constraint)s, "t".
 5492    /// The meet ignores type parameters. (Really?? --KRML)
 5493    /// It is assumed that "meet" on entry already includes the meet of all proxies
 5494    /// in "visited". The empty meet is represented by "null".
 5495    /// The return is "true" if the meet exists.
 5496    /// </summary>
 520225497    bool MeetOfAllSupertypes(Type t, ref Type meet, ISet<TypeProxy> visited, bool includeT) {
 5498      Contract.Requires(t != null);
 5499      Contract.Requires(visited != null);
 5500
 520225501      t = t.NormalizeExpandKeepConstraints();
 520225502      var proxy = t as TypeProxy;
 861665503      if (proxy != null) {
 344705504        if (visited.Contains(proxy)) {
 3265505          return true;
 5506        }
 338185507        visited.Add(proxy);
 5508
 338185509        var delegatedToOthers = false;
 1568645510        foreach (var c in proxy.SupertypeConstraints) {
 184705511          var s = c.Super.NormalizeExpandKeepConstraints();
 184705512          delegatedToOthers = true;
 184705513          if (!MeetOfAllSupertypes(s, ref meet, visited, true)) {
 05514            return false;
 5515          }
 184705516        }
 494925517        if (!delegatedToOthers) {
 5518          // also consider "Assignable" constraints
 20747165519          foreach (var c in AllXConstraints) {
 6758985520            if (c.ConstraintName == "Assignable" && c.Types[1].Normalize() == proxy) {
 05521              var s = c.Types[0].NormalizeExpandKeepConstraints();
 05522              delegatedToOthers = true;
 05523              if (!MeetOfAllSupertypes(s, ref meet, visited, true)) {
 05524                return false;
 5525              }
 05526            }
 6758985527          }
 156745528        }
 519625529        if (delegatedToOthers) {
 181445530          return true;
 311665531        } else if (!includeT) {
 154925532          return true;
 3645533        } else if (meet == null || meet.Normalize() == proxy) {
 1825534          meet = proxy;
 1825535          return true;
 05536        } else {
 05537          return false;
 5538        }
 5539      }
 5540
 357565541      if (meet == null) {
 178785542        meet = Type.HeadWithProxyArgs(t);
 178785543        return true;
 05544      } else if (Type.IsHeadSupertypeOf(t, meet)) {
 5545        // stick with what we've got
 05546        return true;
 05547      } else if (Type.IsHeadSupertypeOf(meet, t)) {
 05548        meet = Type.HeadWithProxyArgs(t);
 05549        return true;
 05550      } else {
 05551        meet = Type.Meet(meet, Type.HeadWithProxyArgs(t), builtIns);
 05552        return meet != null;
 5553      }
 520225554    }
 5555
 5556    /// <summary>
 5557    /// Check that the type uses formal type parameters in a way that is agreeable with their variance specifications.
 5558    /// "context == Co" says that "type" is allowed to vary in the positive direction.
 5559    /// "context == Contra" says that "type" is allowed to vary in the negative direction.
 5560    /// "context == Non" says that "type" must not vary at all.
 5561    /// * "lax" says that the context is not strict -- type parameters declared to be strict must not be used in a lax c
 5562    /// </summary>
 18285563    public void CheckVariance(Type type, ICallable enclosingTypeDefinition, TypeParameter.TPVariance context, bool lax) 
 5564      Contract.Requires(type != null);
 5565      Contract.Requires(enclosingTypeDefinition != null);
 5566
 18285567      type = type.Normalize();  // we keep constraints, since subset types have their own type-parameter variance specif
 23085568      if (type is BasicType) {
 5569        // fine
 18385570      } else if (type is MapType) {
 105571        var t = (MapType)type;
 5572        // If its an infinite map, the domain's context is lax
 105573        CheckVariance(t.Domain, enclosingTypeDefinition, context, lax || !t.Finite);
 105574        CheckVariance(t.Range, enclosingTypeDefinition, context, lax);
 13785575      } else if (type is SetType) {
 305576        var t = (SetType)type;
 5577        // If its an infinite set, the argument's context is lax
 305578        CheckVariance(t.Arg, enclosingTypeDefinition, context, lax || !t.Finite);
 13585579      } else if (type is CollectionType) {
 205580        var t = (CollectionType)type;
 205581        CheckVariance(t.Arg, enclosingTypeDefinition, context, lax);
 25965582      } else if (type is UserDefinedType) {
 12885583        var t = (UserDefinedType)type;
 19145584        if (t.ResolvedClass is TypeParameter tp) {
 6265585          if (tp.Variance != TypeParameter.TPVariance.Non && tp.Variance != context) {
 05586            reporter.Error(MessageSource.Resolver, t.tok, "formal type parameter '{0}' is not used according to its vari
 6265587          } else if (tp.StrictVariance && lax) {
 5588            string hint;
 05589            if (tp.VarianceSyntax == TypeParameter.TPVarianceSyntax.NonVariant_Strict) {
 05590              hint = string.Format(" (perhaps try declaring '{0}' as '-{0}' or '!{0}')", tp.Name);
 05591            } else {
 05592              Contract.Assert(tp.VarianceSyntax == TypeParameter.TPVarianceSyntax.Covariant_Strict);
 05593              hint = string.Format(" (perhaps try changing the declaration from '+{0}' to '*{0}')", tp.Name);
 05594            }
 05595            reporter.Error(MessageSource.Resolver, t.tok, "formal type parameter '{0}' is not used according to its vari
 05596          }
 12885597        } else {
 6625598          var resolvedClass = t.ResolvedClass;
 6625599          Contract.Assert(resolvedClass != null);  // follows from that the given type was successfully resolved
 6625600          Contract.Assert(resolvedClass.TypeArgs.Count == t.TypeArgs.Count);
 6625601          if (lax) {
 5602            // we have to be careful about uses of the type being defined
 05603            var cg = enclosingTypeDefinition.EnclosingModule.CallGraph;
 05604            var t0 = resolvedClass as ICallable;
 05605            if (t0 != null && cg.GetSCCRepresentative(t0) == cg.GetSCCRepresentative(enclosingTypeDefinition)) {
 05606              reporter.Error(MessageSource.Resolver, t.tok, "using the type being defined ('{0}') here would cause a log
 05607            }
 05608          }
 25725609          for (int i = 0; i < t.TypeArgs.Count; i++) {
 4165610            Type p = t.TypeArgs[i];
 4165611            var tpFormal = resolvedClass.TypeArgs[i];
 4165612            CheckVariance(p, enclosingTypeDefinition,
 4165613              context == TypeParameter.TPVariance.Non ? context :
 4165614              context == TypeParameter.TPVariance.Co ? tpFormal.Variance :
 4165615              TypeParameter.Negate(tpFormal.Variance),
 4165616              lax || !tpFormal.StrictVariance);
 4165617          }
 6625618        }
 12885619      } else {
 05620        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 5621      }
 18285622    }
 5623
 5624    /// <summary>
 5625    /// See ConstrainToIntegerType description for the overload above.
 5626    /// </summary>
 339635627    void ConstrainToIntegerType(IToken tok, Type type, bool allowBitVector, TypeConstraint.ErrorMsg errorMsg) {
 5628      Contract.Requires(tok != null);
 5629      Contract.Requires(type != null);
 5630      Contract.Requires(errorMsg != null);
 5631      // We do two constraints: the first can aid in determining types, but allows bit-vectors; the second excludes bit-
 5632      // However, we reuse the error message, so that only one error gets reported.
 339635633      ConstrainSubtypeRelation(new IntVarietiesSupertype(), type, errorMsg);
 408245634      if (!allowBitVector) {
 68615635        AddXConstraint(tok, "IntegerType", type, errorMsg);
 68615636      }
 339635637    }
 5638
 5639    /// <summary>
 5640    /// Attempts to rewrite a datatype update into more primitive operations, after doing the appropriate resolution che
 5641    /// Upon success, returns that rewritten expression and sets "legalSourceConstructors".
 5642    /// Upon some resolution error, return null.
 5643    ///
 5644    /// Actually, the method returns two expressions (or returns "(null, null)"). The first expression is the desugaring
 5645    /// used when the DatatypeUpdateExpr is used in a ghost context. The second is to be used for a compiled context. In
 5646    /// case, "legalSourceConstructors" contains both ghost and compiled constructors.
 5647    ///
 5648    /// The reason for computing both desugarings here is that it's too early to tell if the DatatypeUpdateExpr is being
 5649    /// a ghost or compiled context. This is a consequence of doing the deguaring so early. But it's also convenient to 
 5650    /// desugaring during resolution, because then the desugaring can be constructed as a non-resolved expression on whi
 5651    /// is called--this is easier than constructing an already-resolved expression.
 5652    /// </summary>
 5653    (Expression, Expression) ResolveDatatypeUpdate(IToken tok, Expression root, DatatypeDecl dt, List<Tuple<IToken, stri
 05654      ResolutionContext resolutionContext, out List<MemberDecl> members, out List<DatatypeCtor> legalSourceConstructors)
 5655      Contract.Requires(tok != null);
 5656      Contract.Requires(root != null);
 5657      Contract.Requires(dt != null);
 5658      Contract.Requires(memberUpdates != null);
 5659      Contract.Requires(resolutionContext != null);
 5660
 05661      legalSourceConstructors = null;
 05662      members = new List<MemberDecl>();
 5663
 5664      // First, compute the list of candidate result constructors, that is, the constructors
 5665      // that have all of the mentioned destructors. Issue errors for duplicated names and for
 5666      // names that are not destructors in the datatype.
 05667      var candidateResultCtors = dt.Ctors;  // list of constructors that have all the so-far-mentioned destructors
 05668      var memberNames = new HashSet<string>();
 05669      var rhsBindings = new Dictionary<string, Tuple<BoundVar/*let variable*/, IdentifierExpr/*id expr for let variable*
 05670      var subst = TypeParameter.SubstitutionMap(dt.TypeArgs, root.Type.NormalizeExpand().TypeArgs);
 05671      foreach (var entry in memberUpdates) {
 05672        var destructor_str = entry.Item2;
 05673        if (memberNames.Contains(destructor_str)) {
 05674          reporter.Error(MessageSource.Resolver, entry.Item1, "duplicate update member '{0}'", destructor_str);
 05675        } else {
 05676          memberNames.Add(destructor_str);
 05677          if (!classMembers[dt].TryGetValue(destructor_str, out var member)) {
 05678            reporter.Error(MessageSource.Resolver, entry.Item1, "member '{0}' does not exist in datatype '{1}'", destruc
 05679          } else if (!(member is DatatypeDestructor)) {
 05680            reporter.Error(MessageSource.Resolver, entry.Item1, "member '{0}' is not a destructor in datatype '{1}'", de
 05681          } else {
 05682            members.Add(member);
 05683            var destructor = (DatatypeDestructor)member;
 05684            var intersection = new List<DatatypeCtor>(candidateResultCtors.Intersect(destructor.EnclosingCtors));
 05685            if (intersection.Count == 0) {
 05686              reporter.Error(MessageSource.Resolver, entry.Item1,
 05687                "updated datatype members must belong to the same constructor (unlike the previously mentioned destructo
 05688                destructor_str, DatatypeDestructor.PrintableCtorNameList(candidateResultCtors, "or"));
 05689            } else {
 05690              candidateResultCtors = intersection;
 05691              if (destructor.IsGhost) {
 05692                rhsBindings.Add(destructor_str, new Tuple<BoundVar, IdentifierExpr, Expression>(null, null, entry.Item3)
 05693              } else {
 05694                var xName = FreshTempVarName(string.Format("dt_update#{0}#", destructor_str), resolutionContext.CodeCont
 05695                var xVar = new BoundVar(new AutoGeneratedToken(tok), xName, destructor.Type.Subst(subst));
 05696                var x = new IdentifierExpr(new AutoGeneratedToken(tok), xVar);
 05697                rhsBindings.Add(destructor_str, new Tuple<BoundVar, IdentifierExpr, Expression>(xVar, x, entry.Item3));
 05698              }
 05699            }
 05700          }
 05701        }
 05702      }
 05703      if (candidateResultCtors.Count == 0) {
 05704        return (null, null);
 5705      }
 5706
 5707      // Check that every candidate result constructor has given a name to all of its parameters.
 05708      var hasError = false;
 05709      foreach (var ctor in candidateResultCtors) {
 05710        if (ctor.Formals.Exists(f => !f.HasName)) {
 05711          reporter.Error(MessageSource.Resolver, tok,
 05712            "candidate result constructor '{0}' has an anonymous parameter (to use in datatype update expression, name a
 05713            ctor.Name);
 05714          hasError = true;
 05715        }
 05716      }
 05717      if (hasError) {
 05718        return (null, null);
 5719      }
 5720
 5721      // The legal source constructors are the candidate result constructors. (Yep, two names for the same thing.)
 05722      legalSourceConstructors = candidateResultCtors;
 05723      Contract.Assert(1 <= legalSourceConstructors.Count);
 5724
 05725      var desugaringForGhostContext = DesugarDatatypeUpdate(tok, root, dt, candidateResultCtors, rhsBindings, resolution
 05726      var nonGhostConstructors = candidateResultCtors.Where(ctor => !ctor.IsGhost).ToList();
 05727      if (nonGhostConstructors.Count == candidateResultCtors.Count) {
 05728        return (desugaringForGhostContext, desugaringForGhostContext);
 5729      }
 05730      var desugaringForCompiledContext = DesugarDatatypeUpdate(tok, root, dt, nonGhostConstructors, rhsBindings, resolut
 05731      return (desugaringForGhostContext, desugaringForCompiledContext);
 05732    }
 5733
 5734    /// <summary>
 5735    // Rewrite the datatype update root.(x := X, y := Y, ...) to:
 5736    ///     var d := root;
 5737    ///     var x := X;  // EXCEPT: don't do this for ghost fields
 5738    ///     var y := Y;
 5739    ///     ..
 5740    ///     if d.CandidateResultConstructor0 then
 5741    ///       CandidateResultConstructor0(x, y, ..., d.f0, d.f1, ...)  // for a ghost field x, use the expression X dire
 5742    ///     else if d.CandidateResultConstructor1 then
 5743    ///       CandidateResultConstructor0(x, y, ..., d.g0, d.g1, ...)
 5744    ///     ...
 5745    ///     else
 5746    ///       CandidateResultConstructorN(x, y, ..., d.k0, d.k1, ...)
 5747    /// </summary>
 5748    private Expression DesugarDatatypeUpdate(IToken tok, Expression root, DatatypeDecl dt, List<DatatypeCtor> candidateR
 05749      Dictionary<string, Tuple<BoundVar, IdentifierExpr, Expression>> rhsBindings, ResolutionContext resolutionContext) 
 5750
 05751      if (candidateResultCtors.Count == 0) {
 05752        return root;
 5753      }
 05754      Expression rewrite = null;
 5755      // Create a unique name for d', the variable we introduce in the let expression
 05756      var dName = FreshTempVarName("dt_update_tmp#", resolutionContext.CodeContext);
 05757      var dVar = new BoundVar(new AutoGeneratedToken(tok), dName, root.Type);
 05758      var d = new IdentifierExpr(new AutoGeneratedToken(tok), dVar);
 05759      Expression body = null;
 05760      candidateResultCtors.Reverse();
 05761      foreach (var crc in candidateResultCtors) {
 5762        // Build the arguments to the datatype constructor, using the updated value in the appropriate slot
 05763        var ctorArguments = new List<Expression>();
 05764        var actualBindings = new List<ActualBinding>();
 05765        foreach (var f in crc.Formals) {
 5766          Expression ctorArg;
 05767          if (rhsBindings.TryGetValue(f.Name, out var info)) {
 05768            ctorArg = info.Item2 ?? info.Item3;
 05769          } else {
 05770            ctorArg = new ExprDotName(tok, d, f.Name, null);
 05771          }
 05772          ctorArguments.Add(ctorArg);
 05773          var bindingName = new Token(tok.line, tok.col) {
 05774            Uri = tok.Uri,
 05775            val = f.Name
 05776          };
 05777          actualBindings.Add(new ActualBinding(bindingName, ctorArg));
 05778        }
 05779        var ctor_call = new DatatypeValue(tok, crc.EnclosingDatatype.Name, crc.Name, actualBindings);
 5780        // in the following line, resolve to root.Type, so that type parameters get filled in appropriately
 05781        ResolveDatatypeValue(resolutionContext, ctor_call, dt, root.Type.NormalizeExpand());
 5782
 05783        if (body == null) {
 05784          body = ctor_call;
 05785        } else {
 5786          // body = if d.crc? then ctor_call else body
 05787          var guard = new ExprDotName(tok, d, crc.QueryField.Name, null);
 05788          body = new ITEExpr(tok, false, guard, ctor_call, body);
 05789        }
 05790      }
 05791      Contract.Assert(body != null); // because there was at least one element in candidateResultCtors
 5792
 5793      // Wrap the let's around body
 05794      rewrite = body;
 05795      foreach (var entry in rhsBindings) {
 05796        if (entry.Value.Item1 != null) {
 05797          var lhs = new CasePattern<BoundVar>(tok, entry.Value.Item1);
 05798          rewrite = new LetExpr(tok, new List<CasePattern<BoundVar>>() { lhs }, new List<Expression>() { entry.Value.Ite
 05799        }
 05800      }
 05801      var dVarPat = new CasePattern<BoundVar>(tok, dVar);
 05802      rewrite = new LetExpr(tok, new List<CasePattern<BoundVar>>() { dVarPat }, new List<Expression>() { root }, rewrite
 05803      Contract.Assert(rewrite != null);
 05804      ResolveExpression(rewrite, resolutionContext);
 05805      return rewrite;
 05806    }
 5807
 5808    public Expression ResolveNameSegment(NameSegment expr, bool isLastNameSegment, List<ActualBinding> args,
 2890055809      ResolutionContext resolutionContext, bool allowMethodCall, bool complain = true) {
 2890055810      return ResolveNameSegment(expr, isLastNameSegment, args, resolutionContext, allowMethodCall, complain, out _);
 2890055811    }
 5812
 5813    /// <summary>
 5814    /// Look up expr.Name in the following order:
 5815    ///  0. Local variable, parameter, or bound variable.
 5816    ///     (Language design note:  If this clashes with something of interest, one can always rename the local variable
 5817    ///  1. Member of enclosing class (an implicit "this" is inserted, if needed)
 5818    ///  2. If isLastNameSegment:
 5819    ///     Unambiguous constructor name of a datatype in the enclosing module (if two constructors have the same name, 
 5820    ///     (Language design note:  If the constructor name is ambiguous or if one of the steps above takes priority, on
 5821    ///  3. Member of the enclosing module (type name or the name of a module)
 5822    ///  4. Static function or method in the enclosing module or its imports
 5823    ///  5. If !isLastNameSegment:
 5824    ///     Unambiguous constructor name of a datatype in the enclosing module
 5825    ///
 5826    /// </summary>
 5827    /// <param name="expr"></param>
 5828    /// <param name="isLastNameSegment">Indicates that the NameSegment is not directly enclosed in another NameSegment o
 5829    /// <param name="args">If the NameSegment is enclosed in an ApplySuffix, then these are the arguments.  The method r
 5830    /// that these arguments, if any, were not used.  If args is non-null and the method does use them, the method retur
 5831    /// that incorporates these arguments.</param>
 5832    /// <param name="resolutionContext"></param>
 5833    /// <param name="allowMethodCall">If false, generates an error if the name denotes a method. If true and the name de
 5834    /// a MemberSelectExpr whose .Member is a Method.</param>
 5835    /// <param name="shadowedModule">If the name being resolved shadows an imported module, then that module is reported
 5836    /// through this parameter.  This happens when module <c>Option</c> in <c>import opened Option</c> also contains a
 5837    /// <c>datatype Option</c>, in which case <c>Option</c> refers to the datatype, not the module
 5838    /// (https://github.com/dafny-lang/dafny/issues/1996).</param>
 3035495839    Expression ResolveNameSegment(NameSegment expr, bool isLastNameSegment, List<ActualBinding> args, ResolutionContext 
 5840      Contract.Requires(expr != null);
 5841      Contract.Requires(!expr.WasResolved());
 5842      Contract.Requires(resolutionContext != null);
 5843      Contract.Ensures(Contract.Result<Expression>() == null || args != null);
 5844
 3035495845      shadowedModule = null;
 5846
 3035495847      if (expr.OptTypeArguments != null) {
 05848        foreach (var ty in expr.OptTypeArguments) {
 05849          ResolveType(expr.tok, ty, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 05850        }
 05851      }
 5852
 3035495853      Expression r = null;  // the resolved expression, if successful
 3035495854      Expression rWithArgs = null;  // the resolved expression after incorporating "args"
 5855
 5856      // For 0:
 5857      IVariable v;
 5858      // For 1:
 5859      // For 1 and 4:
 3035495860      MemberDecl member = null;
 5861      // For 2 and 5:
 5862      // For 3:
 5863
 3035495864      var name = resolutionContext.InReveal ? "reveal_" + expr.Name : expr.Name;
 3035495865      v = scope.Find(name);
 5905095866      if (v != null) {
 5867        // ----- 0. local variable, parameter, or bound variable
 2869605868        if (expr.OptTypeArguments != null) {
 05869          if (complain) {
 05870            reporter.Error(MessageSource.Resolver, expr.tok, "variable '{0}' does not take any type parameters", name);
 05871          } else {
 05872            expr.ResolvedExpression = null;
 05873            return null;
 5874          }
 05875        }
 2869605876        r = new IdentifierExpr(expr.tok, v);
 3109805877      } else if (currentClass is TopLevelDeclWithMembers cl && classMembers.TryGetValue(cl, out var members) && members.
 5878        // ----- 1. member of the enclosing class
 5879        Expression receiver;
 148625880        if (member.IsStatic) {
 74315881          receiver = new StaticReceiverExpr(expr.tok, UserDefinedType.FromTopLevelDecl(expr.tok, currentClass, currentCl
 74315882        } else {
 05883          if (!scope.AllowInstance) {
 05884            if (complain) {
 05885              reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context"); //TODO: R
 05886            } else {
 05887              expr.ResolvedExpression = null;
 05888              return null;
 5889            }
 5890            // nevertheless, set "receiver" to a value so we can continue resolution
 05891          }
 05892          receiver = new ImplicitThisExpr(expr.tok);
 05893          receiver.Type = GetThisType(expr.tok, currentClass);  // resolve here
 05894        }
 74315895        r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, allowMe
 257175896      } else if (isLastNameSegment && moduleInfo.Ctors.TryGetValue(name, out var pair)) {
 5897        // ----- 2. datatype constructor
 91285898        if (ResolveDatatypeConstructor(expr, args, resolutionContext, complain, pair, name, ref r, ref rWithArgs)) {
 05899          return null;
 5900        }
 91885901      } else if (moduleInfo.TopLevels.TryGetValue(name, out var decl)) {
 5902        // ----- 3. Member of the enclosing module
 5903
 5904        // Record which imported module, if any, was shadowed by `name` in the current module.
 305905        shadowedModule = moduleInfo.ShadowedImportedModules.GetValueOrDefault(name);
 5906
 305907        if (decl is AmbiguousTopLevelDecl) {
 05908          var ad = (AmbiguousTopLevelDecl)decl;
 05909          if (complain) {
 05910            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 05911          } else {
 05912            expr.ResolvedExpression = null;
 05913            return null;
 5914          }
 305915        } else {
 5916          // We have found a module name or a type name, neither of which is an expression. However, the NameSegment we'
 5917          // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of t
 5918          // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the com
 5919          // or verifier, just to have a placeholder where we can recorded what we have found.
 605920          if (!isLastNameSegment) {
 305921            if (decl is ClassDecl cd && cd.NonNullTypeDecl != null && name != cd.NonNullTypeDecl.Name) {
 5922              // A possibly-null type C? was mentioned. But it does not have any further members. The program should hav
 5923              // the name of the class, C. Report an error and continue.
 05924              if (complain) {
 05925                reporter.Error(MessageSource.Resolver, expr.tok, "To access members of {0} '{1}', write '{1}', not '{2}'
 05926              } else {
 05927                expr.ResolvedExpression = null;
 05928                return null;
 5929              }
 05930            }
 305931          }
 305932          r = CreateResolver_IdentifierExpr(expr.tok, name, expr.OptTypeArguments, decl);
 305933        }
 5934
 305935      } else if (moduleInfo.StaticMembers.TryGetValue(name, out member)) {
 5936        // ----- 4. static member of the enclosing module
 05937        Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the 
 05938        if (member is AmbiguousMemberDecl) {
 05939          var ambiguousMember = (AmbiguousMemberDecl)member;
 05940          if (complain) {
 05941            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 05942          } else {
 05943            expr.ResolvedExpression = null;
 05944            return null;
 5945          }
 05946        } else {
 05947          var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass, true);
 05948          r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, allow
 05949        }
 5950
 05951      } else if (!isLastNameSegment && moduleInfo.Ctors.TryGetValue(name, out pair)) {
 5952        // ----- 5. datatype constructor
 05953        if (ResolveDatatypeConstructor(expr, args, resolutionContext, complain, pair, name, ref r, ref rWithArgs)) {
 05954          return null;
 5955        }
 5956
 05957      } else {
 5958        // ----- None of the above
 05959        if (complain) {
 05960          if (resolutionContext.InReveal) {
 05961            reporter.Error(MessageSource.Resolver, expr.tok, "cannot reveal '{0}' because no constant, assert label, or 
 05962          } else {
 05963            reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", name);
 05964          }
 05965        } else {
 05966          expr.ResolvedExpression = null;
 05967          return null;
 5968        }
 05969      }
 5970
 3035495971      if (r == null) {
 5972        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 05973        expr.Type = new InferredTypeProxy();
 3035495974      } else {
 3035495975        expr.ResolvedExpression = r;
 3035495976        var rt = r.Type;
 3035495977        var nt = rt.UseInternalSynonym();
 3035495978        expr.Type = nt;
 3035495979      }
 3035495980      return rWithArgs;
 3035495981    }
 5982
 91285983    private bool ResolveDatatypeConstructor(NameSegment expr, List<ActualBinding>/*?*/ args, ResolutionContext resolutio
 5984      Contract.Requires(expr != null);
 5985      Contract.Requires(resolutionContext != null);
 5986
 91285987      if (pair.Item2) {
 5988        // there is more than one constructor with this name
 05989        if (complain) {
 05990          reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor, but does not 
 05991            pair.Item1.EnclosingDatatype.Name);
 05992        } else {
 05993          expr.ResolvedExpression = null;
 05994          return true;
 5995        }
 91285996      } else {
 91285997        if (expr.OptTypeArguments != null) {
 05998          if (complain) {
 05999            reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters ('{
 06000          } else {
 06001            expr.ResolvedExpression = null;
 06002            return true;
 6003          }
 06004        }
 91286005        var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, name, args ?? new List<ActualBinding>())
 91286006        bool ok = ResolveDatatypeValue(resolutionContext, rr, pair.Item1.EnclosingDatatype, null, complain);
 91286007        if (!ok) {
 06008          expr.ResolvedExpression = null;
 06009          return true;
 6010        }
 133516011        if (args == null) {
 42236012          r = rr;
 91286013        } else {
 49056014          r = rr; // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been proper to 
 49056015          rWithArgs = rr;
 49056016        }
 91286017      }
 91286018      return false;
 91286019    }
 6020
 6021    /// <summary>
 6022    /// Look up expr.Name in the following order:
 6023    ///  0. Type parameter
 6024    ///  1. Member of enclosing class (an implicit "this" is inserted, if needed)
 6025    ///  2. Member of the enclosing module (type name or the name of a module)
 6026    ///  3. Static function or method in the enclosing module or its imports
 6027    ///
 6028    /// Note: 1 and 3 are not used now, but they will be of interest when async task types are supported.
 6029    /// </summary>
 2121056030    void ResolveNameSegment_Type(NameSegment expr, ResolutionContext resolutionContext, ResolveTypeOption option, List<T
 6031      Contract.Requires(expr != null);
 6032      Contract.Requires(!expr.WasResolved());
 6033      Contract.Requires(resolutionContext != null);
 6034      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 6035
 2614156036      if (expr.OptTypeArguments != null) {
 4026456037        foreach (var ty in expr.OptTypeArguments) {
 849056038          ResolveType(expr.tok, ty, resolutionContext, option, defaultTypeArguments);
 849056039        }
 493106040      }
 6041
 2121056042      Expression r = null;  // the resolved expression, if successful
 6043
 6044      // For 0:
 6045      TypeParameter tp;
 6046#if ASYNC_TASK_TYPES
 6047      // For 1:
 6048      Dictionary<string, MemberDecl> members;
 6049      // For 1 and 3:
 6050      MemberDecl member = null;
 6051#endif
 6052      // For 2:
 6053
 2121056054      tp = allTypeParameters.Find(expr.Name);
 2130326055      if (tp != null) {
 6056        // ----- 0. type parameter
 18546057        if (expr.OptTypeArguments == null) {
 9276058          r = new Resolver_IdentifierExpr(expr.tok, tp);
 9276059        } else {
 06060          reporter.Error(MessageSource.Resolver, expr.tok, "Type parameter expects no type arguments: {0}", expr.Name);
 06061        }
 6062#if ASYNC_TASK_TYPES  // At the moment, there is no way for a class member to part of a type name, but this changes with
 6063      } else if (currentClass != null && classMembers.TryGetValue(currentClass, out members) && members.TryGetValue(expr
 6064        // ----- 1. member of the enclosing class
 6065        Expression receiver;
 6066        if (member.IsStatic) {
 6067          receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 6068        } else {
 6069          if (!scope.AllowInstance) {
 6070            reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context");
 6071            // nevertheless, set "receiver" to a value so we can continue resolution
 6072          }
 6073          receiver = new ImplicitThisExpr(expr.tok);
 6074          receiver.Type = GetThisType(expr.tok, (ClassDecl)member.EnclosingClass);  // resolve here
 6075        }
 6076        r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMethodCal
 6077#endif
 4232836078      } else if (moduleInfo.TopLevels.TryGetValue(expr.Name, out var decl)) {
 6079        // ----- 2. Member of the enclosing module
 2111786080        if (decl is AmbiguousTopLevelDecl) {
 06081          var ad = (AmbiguousTopLevelDecl)decl;
 06082          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modu
 2111786083        } else {
 6084          // We have found a module name or a type name, neither of which is a type expression. However, the NameSegment
 6085          // looking at may be followed by a further suffix that makes this into a type expresion. We postpone the rest 
 6086          // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the com
 6087          // or verifier, just to have a placeholder where we can recorded what we have found.
 2111786088          r = CreateResolver_IdentifierExpr(expr.tok, expr.Name, expr.OptTypeArguments, decl);
 2111786089        }
 6090
 6091#if ASYNC_TASK_TYPES  // At the moment, there is no way for a class member to part of a type name, but this changes with
 6092      } else if (moduleInfo.StaticMembers.TryGetValue(expr.Name, out member)) {
 6093        // ----- 3. static member of the enclosing module
 6094        Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the 
 6095        if (ReallyAmbiguousThing(ref member)) {
 6096          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one of
 6097        } else {
 6098          var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 6099          r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMethodC
 6100        }
 6101#endif
 2111786102      } else {
 6103        // ----- None of the above
 06104        reporter.Error(MessageSource.Resolver, expr.tok, "Type or type parameter is not declared in this scope: {0} (did
 06105      }
 6106
 2121056107      if (r == null) {
 6108        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06109        expr.Type = new InferredTypeProxy();
 2121056110      } else {
 2121056111        expr.ResolvedExpression = r;
 2121056112        expr.Type = r.Type;
 2121056113      }
 2121056114    }
 6115
 6116    /// <summary>
 6117    /// To resolve "id" in expression "E . id", do:
 6118    ///  * If E denotes a module name M:
 6119    ///      0. If isLastNameSegment:
 6120    ///         Unambiguous constructor name of a datatype in module M (if two constructors have the same name, an error
 6121    ///         (Language design note:  If the constructor name is ambiguous or if one of the steps above takes priority
 6122    ///      1. Member of module M:  sub-module (including submodules of imports), class, datatype, etc.
 6123    ///         (if two imported types have the same name, an error message is produced here)
 6124    ///      2. Static function or method of M._default
 6125    ///    (Note that in contrast to ResolveNameSegment, imported modules, etc. are ignored)
 6126    ///  * If E denotes a type:
 6127    ///      3. Look up id as a member of that type
 6128    ///  * If E denotes an expression:
 6129    ///      4. Let T be the type of E.  Look up id in T.
 6130    /// </summary>
 6131    /// <param name="expr"></param>
 6132    /// <param name="isLastNameSegment">Indicates that the ExprDotName is not directly enclosed in another ExprDotName e
 6133    /// <param name="args">If the ExprDotName is enclosed in an ApplySuffix, then these are the arguments.  The method r
 6134    /// that these arguments, if any, were not used.  If args is non-null and the method does use them, the method retur
 6135    /// that incorporates these arguments.</param>
 6136    /// <param name="resolutionContext"></param>
 6137    /// <param name="allowMethodCall">If false, generates an error if the name denotes a method. If true and the name de
 6138    /// a Resolver_MethodCall.</param>
 160596139    Expression ResolveDotSuffix(ExprDotName expr, bool isLastNameSegment, List<ActualBinding> args, ResolutionContext re
 6140      Contract.Requires(expr != null);
 6141      Contract.Requires(!expr.WasResolved());
 6142      Contract.Requires(resolutionContext != null);
 6143      Contract.Ensures(Contract.Result<Expression>() == null || args != null);
 6144
 6145      // resolve the LHS expression
 6146      // LHS should not be reveal lemma
 160596147      ModuleDecl shadowedImport = null;
 160596148      ResolutionContext nonRevealOpts = resolutionContext with { InReveal = false };
 306036149      if (expr.Lhs is NameSegment) {
 145446150        ResolveNameSegment((NameSegment)expr.Lhs, false, null, nonRevealOpts, false, true, out shadowedImport);
 160596151      } else if (expr.Lhs is ExprDotName) {
 06152        ResolveDotSuffix((ExprDotName)expr.Lhs, false, null, nonRevealOpts, false);
 15156153      } else {
 15156154        ResolveExpression(expr.Lhs, nonRevealOpts);
 15156155      }
 6156
 160596157      if (expr.OptTypeArguments != null) {
 06158        foreach (var ty in expr.OptTypeArguments) {
 06159          ResolveType(expr.tok, ty, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 06160        }
 06161      }
 6162
 160596163      Expression r = null;  // the resolved expression, if successful
 160596164      Expression rWithArgs = null;  // the resolved expression after incorporating "args"
 160596165      MemberDecl member = null;
 6166
 160596167      var name = resolutionContext.InReveal ? "reveal_" + expr.SuffixName : expr.SuffixName;
 160596168      if (!expr.Lhs.WasResolved()) {
 06169        return null;
 6170      }
 160596171      var lhs = expr.Lhs.Resolved;
 160596172      if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 06173        var ri = (Resolver_IdentifierExpr)lhs;
 06174        var sig = ((ModuleDecl)ri.Decl).AccessibleSignature(useCompileSignatures);
 06175        sig = GetSignature(sig);
 6176        // For 0:
 6177        // For 1:
 6178
 06179        if (isLastNameSegment && sig.Ctors.TryGetValue(name, out var pair)) {
 6180          // ----- 0. datatype constructor
 06181          if (pair.Item2) {
 6182            // there is more than one constructor with this name
 06183            reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor in module {2
 06184          } else {
 06185            if (expr.OptTypeArguments != null) {
 06186              reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters (
 06187            }
 06188            var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, name, args ?? new List<ActualBinding
 06189            ResolveDatatypeValue(resolutionContext, rr, pair.Item1.EnclosingDatatype, null);
 6190
 06191            if (args == null) {
 06192              r = rr;
 06193            } else {
 06194              r = rr;  // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been prope
 06195              rWithArgs = rr;
 06196            }
 06197          }
 06198        } else if (sig.TopLevels.TryGetValue(name, out var decl)) {
 6199          // ----- 1. Member of the specified module
 06200          if (decl is AmbiguousTopLevelDecl) {
 06201            var ad = (AmbiguousTopLevelDecl)decl;
 06202            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 06203          } else {
 6204            // We have found a module name or a type name, neither of which is an expression. However, the ExprDotName w
 6205            // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of
 6206            // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the c
 6207            // or verifier, just to have a placeholder where we can recorded what we have found.
 06208            if (!isLastNameSegment) {
 06209              if (decl is ClassDecl cd && cd.NonNullTypeDecl != null && name != cd.NonNullTypeDecl.Name) {
 6210                // A possibly-null type C? was mentioned. But it does not have any further members. The program should h
 6211                // the name of the class, C. Report an error and continue.
 06212                reporter.Error(MessageSource.Resolver, expr.tok, "To access members of {0} '{1}', write '{1}', not '{2}'
 06213              }
 06214            }
 06215            r = CreateResolver_IdentifierExpr(expr.tok, name, expr.OptTypeArguments, decl);
 06216          }
 06217        } else if (sig.StaticMembers.TryGetValue(name, out member)) {
 6218          // ----- 2. static member of the specified module
 06219          Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of th
 06220          if (member is AmbiguousMemberDecl) {
 06221            var ambiguousMember = (AmbiguousMemberDecl)member;
 06222            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 06223          } else {
 06224            var receiver = new StaticReceiverExpr(expr.Lhs.tok, (ClassDecl)member.EnclosingClass, false);
 06225            receiver.ContainerExpression = expr.Lhs;
 06226            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06227          }
 06228        } else {
 06229          reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", name);
 06230        }
 6231
 160896232      } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 306233        var ri = (Resolver_IdentifierExpr)lhs;
 6234        // ----- 3. Look up name in type
 6235        // expand any synonyms
 306236        var ty = new UserDefinedType(expr.tok, ri.Decl.Name, ri.Decl, ri.TypeArgs).NormalizeExpand();
 606237        if (ty.IsDatatype) {
 6238          // ----- LHS is a datatype
 306239          var dt = ty.AsDatatype;
 606240          if (dt.ConstructorsByName != null && dt.ConstructorsByName.TryGetValue(name, out var ctor)) {
 306241            if (expr.OptTypeArguments != null) {
 06242              reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters (
 06243            }
 306244            var rr = new DatatypeValue(expr.tok, ctor.EnclosingDatatype.Name, name, args ?? new List<ActualBinding>());
 306245            ResolveDatatypeValue(resolutionContext, rr, ctor.EnclosingDatatype, ty);
 606246            if (args == null) {
 306247              r = rr;
 306248            } else {
 06249              r = rr;  // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been prope
 06250              rWithArgs = rr;
 06251            }
 306252          }
 306253        }
 306254        var cd = r == null ? ty.AsTopLevelTypeWithMembersBypassInternalSynonym : null;
 306255        if (cd != null) {
 6256          // ----- LHS is a type with members
 06257          if (classMembers.TryGetValue(cd, out var members) && members.TryGetValue(name, out member)) {
 06258            if (!VisibleInScope(member)) {
 06259              reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' has not been imported in this scope and can
 06260            }
 06261            if (!member.IsStatic) {
 06262              reporter.Error(MessageSource.Resolver, expr.tok, "accessing member '{0}' requires an instance expression",
 6263              // nevertheless, continue creating an expression that approximates a correct one
 06264            }
 06265            var receiver = new StaticReceiverExpr(expr.Lhs.tok, (UserDefinedType)ty.NormalizeExpand(), (TopLevelDeclWith
 06266            receiver.ContainerExpression = expr.Lhs;
 06267            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06268          }
 06269        }
 306270        if (r == null) {
 06271          reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in {2} '{1}'", name, ri.Decl.Nam
 06272        }
 320886273      } else if (lhs != null) {
 6274        // ----- 4. Look up name in the type of the Lhs
 160296275        member = ResolveMember(expr.tok, expr.Lhs.Type, name, out var tentativeReceiverType);
 320586276        if (member != null) {
 6277          Expression receiver;
 320586278          if (!member.IsStatic) {
 160296279            receiver = expr.Lhs;
 160296280            AddAssignableConstraint(expr.tok, tentativeReceiverType, receiver.Type, "receiver type ({1}) does not have a
 160296281            r = ResolveExprDotCall(expr.tok, receiver, tentativeReceiverType, member, args, expr.OptTypeArguments, resol
 160296282          } else {
 06283            receiver = new StaticReceiverExpr(expr.tok, (UserDefinedType)tentativeReceiverType, (TopLevelDeclWithMembers
 06284            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06285          }
 160296286        }
 160296287      }
 6288
 160596289      if (r == null) {
 6290        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06291        expr.Type = new InferredTypeProxy();
 160596292      } else {
 160596293        CheckForAmbiguityInShadowedImportedModule(shadowedImport, name, expr.tok, useCompileSignatures, isLastNameSegmen
 160596294        expr.ResolvedExpression = r;
 160596295        expr.Type = r.Type;
 160596296      }
 160596297      return rWithArgs;
 160596298    }
 6299
 6300    /// <summary>
 6301    /// Check whether the name we just resolved may have been resolved differently if we didn't allow member `M.M` of
 6302    /// module `M` to shadow `M` when the user writes `import opened M`.  Raising an error in that case allowed us to
 6303    /// change the behavior of `import opened` without silently changing the meaning of existing programs.
 6304    /// (https://github.com/dafny-lang/dafny/issues/1996)
 6305    ///
 6306    /// Note the extra care for the constructor case, which is needed because the constructors of datatype `M.M` are
 6307    /// exposed through both `M` and `M.M`, without ambiguity.
 6308    /// </summary>
 6309    private void CheckForAmbiguityInShadowedImportedModule(ModuleDecl moduleDecl, string name,
 160596310      IToken tok, bool useCompileSignatures, bool isLastNameSegment) {
 160596311      if (moduleDecl != null && NameConflictsWithModuleContents(moduleDecl, name, useCompileSignatures, isLastNameSegmen
 06312        reporter.Error(MessageSource.Resolver, tok,
 06313          "Reference to member '{0}' is ambiguous: name '{1}' shadows an import-opened module of the same name, and "
 06314          + "both have a member '{0}'. To solve this issue, give a different name to the imported module using "
 06315          + "`import opened XYZ = ...` instead of `import opened ...`.",
 06316          name, moduleDecl.Name);
 06317      }
 160596318    }
 6319
 06320    private bool NameConflictsWithModuleContents(ModuleDecl moduleDecl, string name, bool useCompileSignatures, bool isL
 06321      var sig = GetSignature(moduleDecl.AccessibleSignature(useCompileSignatures));
 06322      return (
 06323        (isLastNameSegment
 06324         && sig.Ctors.GetValueOrDefault(name) is { Item1: var constructor, Item2: var ambiguous }
 06325         && !ambiguous && constructor.EnclosingDatatype.Name != moduleDecl.Name)
 06326        || sig.TopLevels.ContainsKey(name)
 06327        || sig.StaticMembers.ContainsKey(name)
 06328      );
 06329    }
 6330
 6331    Expression ResolveExprDotCall(IToken tok, Expression receiver, Type receiverTypeBound/*?*/,
 234606332      MemberDecl member, List<ActualBinding> args, List<Type> optTypeArguments, ResolutionContext resolutionContext, boo
 6333      Contract.Requires(tok != null);
 6334      Contract.Requires(receiver != null);
 6335      Contract.Requires(receiver.WasResolved());
 6336      Contract.Requires(member != null);
 6337      Contract.Requires(resolutionContext != null && resolutionContext.CodeContext != null);
 6338
 234606339      var rr = new MemberSelectExpr(tok, receiver, member.Name);
 234606340      rr.Member = member;
 6341
 6342      // Now, fill in rr.Type.  This requires taking into consideration the type parameters passed to the receiver's typ
 6343      // parameters used in this NameSegment/ExprDotName.
 6344      // Add to "subst" the type parameters given to the member's class/datatype
 234606345      rr.TypeApplication_AtEnclosingClass = new List<Type>();
 234606346      rr.TypeApplication_JustMember = new List<Type>();
 6347      Dictionary<TypeParameter, Type> subst;
 234606348      var rType = (receiverTypeBound ?? receiver.Type).NormalizeExpand();
 463606349      if (rType is UserDefinedType udt && udt.ResolvedClass != null) {
 229006350        subst = TypeParameter.SubstitutionMap(udt.ResolvedClass.TypeArgs, udt.TypeArgs);
 229006351        if (member.EnclosingClass == null) {
 6352          // this can happen for some special members, like real.Floor
 229006353        } else {
 229006354          rr.TypeApplication_AtEnclosingClass.AddRange(rType.AsParentType(member.EnclosingClass).TypeArgs);
 229006355        }
 234606356      } else {
 5606357        var vtd = AsValuetypeDecl(rType);
 11206358        if (vtd != null) {
 5606359          Contract.Assert(vtd.TypeArgs.Count == rType.TypeArgs.Count);
 5606360          subst = TypeParameter.SubstitutionMap(vtd.TypeArgs, rType.TypeArgs);
 5606361          rr.TypeApplication_AtEnclosingClass.AddRange(rType.TypeArgs);
 5606362        } else {
 06363          Contract.Assert(rType.TypeArgs.Count == 0);
 06364          subst = new Dictionary<TypeParameter, Type>();
 06365        }
 5606366      }
 6367
 394896368      if (member is Field) {
 160296369        var field = (Field)member;
 160296370        if (optTypeArguments != null) {
 06371          reporter.Error(MessageSource.Resolver, tok, "a field ({0}) does not take any type arguments (got {1})", field.
 06372        }
 160296373        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 160296374        rr.Type = field.Type.Subst(subst);
 234606375      } else if (member is Function) {
 06376        var fn = (Function)member;
 06377        if (fn is TwoStateFunction && !resolutionContext.IsTwoState) {
 06378          reporter.Error(MessageSource.Resolver, tok, "two-state function ('{0}') can only be called in a two-state cont
 06379        }
 06380        int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count;
 06381        if (optTypeArguments != null && suppliedTypeArguments != fn.TypeArgs.Count) {
 06382          reporter.Error(MessageSource.Resolver, tok, "function '{0}' expects {1} type argument{2} (got {3})",
 06383            member.Name, fn.TypeArgs.Count, Util.Plural(fn.TypeArgs.Count), suppliedTypeArguments);
 06384        }
 06385        for (int i = 0; i < fn.TypeArgs.Count; i++) {
 06386          var ta = i < suppliedTypeArguments ? optTypeArguments[i] : new InferredTypeProxy();
 06387          rr.TypeApplication_JustMember.Add(ta);
 06388          subst.Add(fn.TypeArgs[i], ta);
 06389        }
 06390        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 06391        rr.Type = SelectAppropriateArrowTypeForFunction(fn, subst, builtIns);
 74316392      } else {
 6393        // the member is a method
 74316394        var m = (Method)member;
 74316395        if (!allowMethodCall) {
 6396          // it's a method and method calls are not allowed in the given context
 06397          reporter.Error(MessageSource.Resolver, tok, "expression is not allowed to invoke a {0} ({1})", member.WhatKind
 06398        }
 74316399        int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count;
 74316400        if (optTypeArguments != null && suppliedTypeArguments != m.TypeArgs.Count) {
 06401          reporter.Error(MessageSource.Resolver, tok, "method '{0}' expects {1} type argument{2} (got {3})",
 06402            member.Name, m.TypeArgs.Count, Util.Plural(m.TypeArgs.Count), suppliedTypeArguments);
 06403        }
 277836404        for (int i = 0; i < m.TypeArgs.Count; i++) {
 43076405          var ta = i < suppliedTypeArguments ? optTypeArguments[i] : new InferredTypeProxy();
 43076406          rr.TypeApplication_JustMember.Add(ta);
 43076407          subst.Add(m.TypeArgs[i], ta);
 43076408        }
 74316409        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 152386410        rr.ResolvedOutparameterTypes = m.Outs.ConvertAll(f => f.Type.Subst(subst));
 74316411        rr.Type = new InferredTypeProxy();  // fill in this field, in order to make "rr" resolved
 74316412      }
 234606413      return rr;
 234606414    }
 6415
 123366416    public MethodCallInformation ResolveApplySuffix(ApplySuffix e, ResolutionContext resolutionContext, bool allowMethod
 6417      Contract.Requires(e != null);
 6418      Contract.Requires(resolutionContext != null);
 6419      Contract.Ensures(Contract.Result<MethodCallInformation>() == null || allowMethodCall);
 123366420      Expression r = null;  // upon success, the expression to which the ApplySuffix resolves
 123366421      var errorCount = reporter.Count(ErrorLevel.Error);
 246726422      if (e.Lhs is NameSegment) {
 123366423        r = ResolveNameSegment((NameSegment)e.Lhs, true, e.Bindings.ArgumentBindings, resolutionContext, allowMethodCall
 6424        // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Arg
 123366425      } else if (e.Lhs is ExprDotName) {
 06426        r = ResolveDotSuffix((ExprDotName)e.Lhs, true, e.Bindings.ArgumentBindings, resolutionContext, allowMethodCall);
 6427        // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Arg
 06428      } else {
 06429        ResolveExpression(e.Lhs, resolutionContext);
 06430      }
 123366431      if (e.Lhs.Type == null) {
 6432        // some error had been detected during the attempted resolution of e.Lhs
 06433        e.Lhs.Type = new InferredTypeProxy();
 06434      }
 123366435      Label atLabel = null;
 123366436      if (e.AtTok != null) {
 06437        atLabel = DominatingStatementLabels.Find(e.AtTok.val);
 06438        if (atLabel == null) {
 06439          reporter.Error(MessageSource.Resolver, e.AtTok, "no label '{0}' in scope at this time", e.AtTok.val);
 06440        }
 06441      }
 197676442      if (r == null) {
 74316443        var improvedType = PartiallyResolveTypeForMemberSelection(e.Lhs.tok, e.Lhs.Type, "_#apply");
 74316444        var fnType = improvedType.AsArrowType;
 148626445        if (fnType == null) {
 74316446          var lhs = e.Lhs.Resolved;
 74316447          if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 06448            reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a function", ((Resolver_Ident
 74316449          } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 06450            var ri = (Resolver_IdentifierExpr)lhs;
 06451            reporter.Error(MessageSource.Resolver, e.tok, "name of {0} ({1}) is used as a function", ri.Decl.WhatKind, r
 74316452          } else {
 148626453            if (lhs is MemberSelectExpr mse && mse.Member is Method) {
 74316454              if (atLabel != null) {
 06455                Contract.Assert(mse != null); // assured by the parser
 06456                if (mse.Member is TwoStateLemma) {
 06457                  mse.AtLabel = atLabel;
 06458                } else {
 06459                  reporter.Error(MessageSource.Resolver, e.AtTok, "an @-label can only be applied to a two-state lemma")
 06460                }
 06461              }
 148626462              if (allowMethodCall) {
 74316463                Contract.Assert(!e.Bindings.WasResolved); // we expect that .Bindings has not yet been processed, so we 
 74316464                var tok = Options.Get(DafnyConsolePrinter.ShowSnippets) ? e.RangeToken.ToToken() : e.tok;
 74316465                var cRhs = new MethodCallInformation(tok, mse, e.Bindings.ArgumentBindings);
 74316466                return cRhs;
 06467              } else {
 06468                reporter.Error(MessageSource.Resolver, e.tok, "{0} call is not allowed to be used in an expression conte
 06469              }
 06470            } else if (lhs != null) {  // if e.Lhs.Resolved is null, then e.Lhs was not successfully resolved and an err
 06471              reporter.Error(MessageSource.Resolver, e.tok, "non-function expression (of type {0}) is called with parame
 06472            }
 06473          }
 6474          // resolve the arguments, even in the presence of the errors above
 06475          foreach (var binding in e.Bindings.ArgumentBindings) {
 06476            ResolveExpression(binding.Actual, resolutionContext);
 06477          }
 06478        } else {
 06479          var mse = e.Lhs is NameSegment || e.Lhs is ExprDotName ? e.Lhs.Resolved as MemberSelectExpr : null;
 06480          var callee = mse == null ? null : mse.Member as Function;
 06481          if (atLabel != null && !(callee is TwoStateFunction)) {
 06482            reporter.Error(MessageSource.Resolver, e.AtTok, "an @-label can only be applied to a two-state function");
 06483            atLabel = null;
 06484          }
 06485          if (callee != null) {
 6486            // produce a FunctionCallExpr instead of an ApplyExpr(MemberSelectExpr)
 06487            var rr = new FunctionCallExpr(e.Lhs.tok, callee.Name, mse.Obj, e.tok, e.CloseParen, e.Bindings, atLabel) {
 06488              Function = callee,
 06489              TypeApplication_AtEnclosingClass = mse.TypeApplication_AtEnclosingClass,
 06490              TypeApplication_JustFunction = mse.TypeApplication_JustMember
 06491            };
 06492            var typeMap = BuildTypeArgumentSubstitute(mse.TypeArgumentSubstitutionsAtMemberDeclaration());
 06493            ResolveActualParameters(rr.Bindings, callee.Formals, e.tok, callee, resolutionContext, typeMap, callee.IsSta
 06494            rr.Type = callee.ResultType.Subst(typeMap);
 06495            if (errorCount == reporter.Count(ErrorLevel.Error)) {
 06496              Contract.Assert(!(mse.Obj is StaticReceiverExpr) || callee.IsStatic);  // this should have been checked al
 06497              Contract.Assert(callee.Formals.Count == rr.Args.Count);  // this should have been checked already
 06498            }
 06499            r = rr;
 06500          } else {
 6501            List<Formal> formals;
 06502            if (callee != null) {
 06503              formals = callee.Formals;
 06504            } else {
 06505              formals = new List<Formal>();
 06506              for (var i = 0; i < fnType.Args.Count; i++) {
 06507                var argType = fnType.Args[i];
 06508                var formal = new ImplicitFormal(e.tok, "_#p" + i, argType, true, false);
 06509                formals.Add(formal);
 06510              }
 06511            }
 06512            ResolveActualParameters(e.Bindings, formals, e.tok, fnType, resolutionContext, new Dictionary<TypeParameter,
 06513            r = new ApplyExpr(e.Lhs.tok, e.Lhs, e.Args, e.CloseParen);
 06514            r.Type = fnType.Result;
 06515          }
 06516        }
 06517      }
 49056518      if (r == null) {
 6519        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06520        e.Type = new InferredTypeProxy();
 49056521      } else {
 49056522        e.ResolvedExpression = r;
 49056523        e.Type = r.Type;
 49056524      }
 49056525      return null;
 123366526    }
 6527
 6528    /// <summary>
 6529    /// the return value is false iff there is an error in resolving the datatype value;
 6530    /// if there is an error then an error message is emitted iff complain is true
 6531    /// </summary>
 252436532    private bool ResolveDatatypeValue(ResolutionContext resolutionContext, DatatypeValue dtv, DatatypeDecl dt, Type ty, 
 6533      Contract.Requires(resolutionContext != null);
 6534      Contract.Requires(dtv != null);
 6535      Contract.Requires(dt != null);
 6536      Contract.Requires(ty == null || (ty.AsDatatype == dt && ty.TypeArgs.Count == dt.TypeArgs.Count));
 6537
 252436538      var ok = true;
 252436539      var gt = new List<Type>(dt.TypeArgs.Count);
 252436540      var subst = new Dictionary<TypeParameter, Type>();
 1940156541      for (int i = 0; i < dt.TypeArgs.Count; i++) {
 478436542        Type t = ty == null ? new InferredTypeProxy() : ty.TypeArgs[i];
 478436543        gt.Add(t);
 478436544        dtv.InferredTypeArgs.Add(t);
 478436545        subst.Add(dt.TypeArgs[i], t);
 478436546      }
 6547      // Construct a resolved type directly, as we know the declaration is dt.
 252436548      dtv.Type = new UserDefinedType(dtv.tok, dt.Name, dt, gt);
 6549
 252436550      if (!dt.ConstructorsByName.TryGetValue(dtv.MemberName, out var ctor)) {
 06551        ok = false;
 06552        if (complain) {
 06553          reporter.Error(MessageSource.Resolver, dtv.tok, "undeclared constructor {0} in datatype {1}", dtv.MemberName, 
 06554        }
 252436555      } else {
 252436556        Contract.Assert(ctor != null);  // follows from postcondition of TryGetValue
 252436557        dtv.Ctor = ctor;
 252436558      }
 504866559      if (complain && ctor != null) {
 252436560        ResolveActualParameters(dtv.Bindings, ctor.Formals, dtv.tok, ctor, resolutionContext, subst, null);
 252436561      } else {
 6562        // still resolve the expressions
 06563        foreach (var binding in dtv.Bindings.ArgumentBindings) {
 06564          ResolveExpression(binding.Actual, resolutionContext);
 06565        }
 06566        dtv.Bindings.AcceptArgumentExpressionsAsExactParameterList();
 06567      }
 6568
 252436569      return ok && ctor.Formals.Count == dtv.Arguments.Count;
 252436570    }
 6571
 06572    public void ResolveFunctionCallExpr(FunctionCallExpr e, ResolutionContext resolutionContext) {
 6573      Contract.Requires(e != null);
 6574      Contract.Requires(e.Type == null);  // should not have been type checked before
 6575
 06576      ResolveReceiver(e.Receiver, resolutionContext);
 06577      Contract.Assert(e.Receiver.Type != null);  // follows from postcondition of ResolveExpression
 6578
 06579      var member = ResolveMember(e.tok, e.Receiver.Type, e.Name, out var tentativeReceiverType);
 6580#if !NO_WORK_TO_BE_DONE
 06581      var ctype = (UserDefinedType)tentativeReceiverType;
 6582#endif
 06583      if (member == null) {
 6584        // error has already been reported by ResolveMember
 06585      } else if (member is Method) {
 06586        reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} refers to a method, but only functions can be 
 06587      } else if (!(member is Function)) {
 06588        reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} does not refer to a function", e.Name, cce.Non
 06589      } else {
 06590        Function function = (Function)member;
 06591        e.Function = function;
 06592        if (function is TwoStateFunction && !resolutionContext.IsTwoState) {
 06593          reporter.Error(MessageSource.Resolver, e.tok, "a two-state function can be used only in a two-state context");
 06594        }
 06595        if (e.Receiver is StaticReceiverExpr && !function.IsStatic) {
 06596          reporter.Error(MessageSource.Resolver, e, "an instance function must be selected via an object, not just a cla
 06597        }
 06598        Contract.Assert(ctype != null);  // follows from postcondition of ResolveMember
 06599        if (!function.IsStatic) {
 06600          if (!scope.AllowInstance && e.Receiver is ThisExpr) {
 6601            // The call really needs an instance, but that instance is given as 'this', which is not
 6602            // available in this context.  In most cases, occurrences of 'this' inside e.Receiver would
 6603            // have been caught in the recursive call to resolve e.Receiver, but not the specific case
 6604            // of e.Receiver being 'this' (explicitly or implicitly), for that case needs to be allowed
 6605            // in the event that a static function calls another static function (and note that we need the
 6606            // type of the receiver in order to find the method, so we could not have made this check
 6607            // earlier).
 06608            reporter.Error(MessageSource.Resolver, e.Receiver, "'this' is not allowed in a 'static' context");
 06609          } else if (e.Receiver is StaticReceiverExpr) {
 06610            reporter.Error(MessageSource.Resolver, e.Receiver, "call to instance function requires an instance");
 06611          }
 06612        }
 6613        // build the type substitution map
 06614        var typeMap = new Dictionary<TypeParameter, Type>();
 06615        for (int i = 0; i < ctype.TypeArgs.Count; i++) {
 06616          typeMap.Add(ctype.ResolvedClass.TypeArgs[i], ctype.TypeArgs[i]);
 06617        }
 06618        var typeThatEnclosesMember = ctype.AsParentType(member.EnclosingClass);
 06619        e.TypeApplication_AtEnclosingClass = new List<Type>();
 06620        for (int i = 0; i < typeThatEnclosesMember.TypeArgs.Count; i++) {
 06621          e.TypeApplication_AtEnclosingClass.Add(typeThatEnclosesMember.TypeArgs[i]);
 06622        }
 06623        e.TypeApplication_JustFunction = new List<Type>();
 06624        foreach (TypeParameter p in function.TypeArgs) {
 06625          var ty = new ParamTypeProxy(p);
 06626          typeMap.Add(p, ty);
 06627          e.TypeApplication_JustFunction.Add(ty);
 06628        }
 06629        Dictionary<TypeParameter, Type> subst = BuildTypeArgumentSubstitute(typeMap);
 6630
 6631        // type check the arguments
 06632        ResolveActualParameters(e.Bindings, function.Formals, e.tok, function, resolutionContext, subst, function.IsStat
 6633
 06634        e.Type = function.ResultType.Subst(subst).NormalizeExpand();
 06635      }
 06636    }
 6637
 06638    void ResolveReceiver(Expression expr, ResolutionContext resolutionContext) {
 6639      Contract.Requires(expr != null);
 6640      Contract.Ensures(expr.Type != null);
 6641
 06642      if (expr is ThisExpr && !expr.WasResolved()) {
 6643        // Allow 'this' here, regardless of scope.AllowInstance.  The caller is responsible for
 6644        // making sure 'this' does not really get used when it's not available.
 06645        Contract.Assume(currentClass != null);  // this is really a precondition, in this case
 06646        expr.Type = GetThisType(expr.tok, currentClass);
 06647      } else {
 06648        ResolveExpression(expr, resolutionContext);
 06649      }
 06650    }
 6651
 318346652    void ResolveSeqSelectExpr(SeqSelectExpr e, ResolutionContext resolutionContext) {
 6653      Contract.Requires(e != null);
 318346654      if (e.Type != null) {
 6655        // already resolved
 06656        return;
 6657      }
 6658
 318346659      ResolveExpression(e.Seq, resolutionContext);
 318346660      Contract.Assert(e.Seq.Type != null);  // follows from postcondition of ResolveExpression
 6661
 620876662      if (e.SelectOne) {
 302536663        AddXConstraint(e.tok, "Indexable", e.Seq.Type, "element selection requires a sequence, array, multiset, or map (
 302536664        ResolveExpression(e.E0, resolutionContext);
 302536665        AddXConstraint(e.E0.tok, "ContainerIndex", e.Seq.Type, e.E0.Type, "incorrect type for selection into {0} (got {1
 302536666        Contract.Assert(e.E1 == null);
 302536667        e.Type = new InferredTypeProxy() { KeepConstraints = true };
 302536668        AddXConstraint(e.tok, "ContainerResult",
 302536669          e.Seq.Type, e.Type,
 302536670          new SeqSelectOneErrorMsg(e.tok, e.Seq.Type, e.Type));
 318346671      } else {
 15816672        AddXConstraint(e.tok, "MultiIndexable", e.Seq.Type, "multi-selection of elements requires a sequence or array (g
 31626673        if (e.E0 != null) {
 15816674          ResolveExpression(e.E0, resolutionContext);
 15816675          AddXConstraint(e.E0.tok, "ContainerIndex", e.Seq.Type, e.E0.Type, "incorrect type for selection into {0} (got 
 15816676          ConstrainSubtypeRelation(NewIntegerBasedProxy(e.tok), e.E0.Type, e.E0, "wrong number of indices for multi-sele
 15816677        }
 31626678        if (e.E1 != null) {
 15816679          ResolveExpression(e.E1, resolutionContext);
 15816680          AddXConstraint(e.E1.tok, "ContainerIndex", e.Seq.Type, e.E1.Type, "incorrect type for selection into {0} (got 
 15816681          ConstrainSubtypeRelation(NewIntegerBasedProxy(e.tok), e.E1.Type, e.E1, "wrong number of indices for multi-sele
 15816682        }
 15816683        var resultType = new InferredTypeProxy() { KeepConstraints = true };
 15816684        e.Type = new SeqType(resultType);
 15816685        AddXConstraint(e.tok, "ContainerResult", e.Seq.Type, resultType, "multi-selection has type {0} which is incompat
 15816686      }
 318346687    }
 6688
 6689  }
 6690
 6691  public class MethodCallInformation {
 6692    public readonly IToken Tok;
 6693    public readonly MemberSelectExpr Callee;
 6694    public readonly List<ActualBinding> ActualParameters;
 6695
 6696    [ContractInvariantMethod]
 6697    void ObjectInvariant() {
 6698      Contract.Invariant(Tok != null);
 6699      Contract.Invariant(Callee != null);
 6700      Contract.Invariant(Callee.Member is Method);
 6701      Contract.Invariant(ActualParameters != null);
 6702    }
 6703
 6704    public MethodCallInformation(IToken tok, MemberSelectExpr callee, List<ActualBinding> actualParameters) {
 6705      Contract.Requires(tok != null);
 6706      Contract.Requires(callee != null);
 6707      Contract.Requires(callee.Member is Method);
 6708      Contract.Requires(actualParameters != null);
 6709      this.Tok = tok;
 6710      this.Callee = callee;
 6711      this.ActualParameters = actualParameters;
 6712    }
 6713  }
 6714}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/Resolver.cs

#LineLine coverage
 1//-----------------------------------------------------------------------------
 2//
 3// Copyright (C) Microsoft Corporation.  All Rights Reserved.
 4// Copyright by the contributors to the Dafny Project
 5// SPDX-License-Identifier: MIT
 6//
 7//-----------------------------------------------------------------------------
 8using System;
 9using System.Collections.Generic;
 10using System.Linq;
 11using System.Numerics;
 12using System.Diagnostics.Contracts;
 13using System.IO;
 14using System.Reflection;
 15using JetBrains.Annotations;
 16using Microsoft.BaseTypes;
 17using Microsoft.Boogie;
 18using Microsoft.CodeAnalysis.CSharp.Syntax;
 19using Microsoft.Dafny.Plugins;
 20using static Microsoft.Dafny.ErrorRegistry;
 21
 22namespace Microsoft.Dafny {
 23  interface ICanResolve {
 24    void Resolve(Resolver resolver, ResolutionContext context);
 25  }
 26
 27  public enum FrameExpressionUse { Reads, Modifies, Unchanged }
 28
 29  public partial class Resolver {
 489248230    public DafnyOptions Options { get; }
 31    public readonly BuiltIns builtIns;
 32
 33    public ErrorReporter reporter;
 30634    ModuleSignature moduleInfo = null;
 35
 35754636    public ErrorReporter Reporter => reporter;
 5509237    public List<TypeConstraint.ErrorMsg> TypeConstraintErrorsToBeReported { get; } = new();
 38
 039    private bool RevealedInScope(Declaration d) {
 40      Contract.Requires(d != null);
 41      Contract.Requires(moduleInfo != null);
 42      Contract.Requires(moduleInfo.VisibilityScope != null);
 43
 044      return useCompileSignatures || d.IsRevealedInScope(moduleInfo.VisibilityScope);
 045    }
 46
 3120947    private bool VisibleInScope(Declaration d) {
 48      Contract.Requires(d != null);
 49      Contract.Requires(moduleInfo != null);
 50      Contract.Requires(moduleInfo.VisibilityScope != null);
 51
 3120952      return useCompileSignatures || d.IsVisibleInScope(moduleInfo.VisibilityScope);
 3120953    }
 54
 30655    public FreshIdGenerator defaultTempVarIdGenerator = new FreshIdGenerator();
 56
 057    public string FreshTempVarName(string prefix, ICodeContext context) {
 058      var gen = context is Declaration decl ? decl.IdGenerator : defaultTempVarIdGenerator;
 059      var freshTempVarName = gen.FreshId(prefix);
 060      return freshTempVarName;
 061    }
 62
 63    interface IAmbiguousThing<Thing> {
 64      /// <summary>
 65      /// Returns a plural number of non-null Thing's
 66      /// </summary>
 67      ISet<Thing> Pool { get; }
 68    }
 69
 70    class AmbiguousThingHelper<Thing> where Thing : class {
 071      public static Thing Create(ModuleDefinition m, Thing a, Thing b, IEqualityComparer<Thing> eq, out ISet<Thing> s) {
 72        Contract.Requires(a != null);
 73        Contract.Requires(b != null);
 74        Contract.Requires(eq != null);
 75        Contract.Ensures(Contract.Result<Thing>() != null ||
 76                         Contract.ValueAtReturn(out s) != null || 2 <= Contract.ValueAtReturn(out s).Count);
 077        s = null;
 078        if (eq.Equals(a, b)) {
 079          return a;
 80        }
 81
 082        ISet<Thing> sa = a is IAmbiguousThing<Thing> ? ((IAmbiguousThing<Thing>)a).Pool : new HashSet<Thing>() { a };
 083        ISet<Thing> sb = b is IAmbiguousThing<Thing> ? ((IAmbiguousThing<Thing>)b).Pool : new HashSet<Thing>() { b };
 084        var union = new HashSet<Thing>(sa.Union(sb, eq));
 085        if (sa.Count == union.Count) {
 86          // sb is a subset of sa
 087          return a;
 088        } else if (sb.Count == union.Count) {
 89          // sa is a subset of sb
 090          return b;
 091        } else {
 092          s = union;
 093          Contract.Assert(2 <= s.Count);
 094          return null;
 95        }
 096      }
 97
 098      public static string Name(ISet<Thing> s, Func<Thing, string> name) {
 99        Contract.Requires(s != null);
 100        Contract.Requires(s.Count != 0);
 0101        string nm = null;
 0102        foreach (var thing in s) {
 0103          string n = name(thing);
 0104          if (nm == null) {
 0105            nm = n;
 0106          } else {
 0107            nm += "/" + n;
 0108          }
 0109        }
 110
 0111        return nm;
 0112      }
 113
 0114      public static string ModuleNames(IAmbiguousThing<Thing> amb, Func<Thing, string> moduleName) {
 115        Contract.Requires(amb != null);
 116        Contract.Ensures(Contract.Result<string>() != null);
 0117        string nm = null;
 0118        foreach (var d in amb.Pool) {
 0119          if (nm == null) {
 0120            nm = moduleName(d);
 0121          } else {
 0122            nm += ", " + moduleName(d);
 0123          }
 0124        }
 125
 0126        return nm;
 0127      }
 128    }
 129
 130    public class AmbiguousTopLevelDecl : TopLevelDecl, IAmbiguousThing<TopLevelDecl> // only used with "classes"
 131    {
 0132      public static TopLevelDecl Create(ModuleDefinition m, TopLevelDecl a, TopLevelDecl b) {
 0133        var t = AmbiguousThingHelper<TopLevelDecl>.Create(m, a, b, new Eq(), out var s);
 0134        return t ?? new AmbiguousTopLevelDecl(m, AmbiguousThingHelper<TopLevelDecl>.Name(s, tld => tld.Name), s);
 0135      }
 136
 137      class Eq : IEqualityComparer<TopLevelDecl> {
 0138        public bool Equals(TopLevelDecl d0, TopLevelDecl d1) {
 139          // We'd like to resolve any AliasModuleDecl to whatever module they refer to.
 140          // It seems that the only way to do that is to look at alias.Signature.ModuleDef,
 141          // but that is a ModuleDefinition, which is not a TopLevelDecl.  Therefore, we
 142          // convert to a ModuleDefinition anything that might refer to something that an
 143          // AliasModuleDecl can refer to; this is AliasModuleDecl and LiteralModuleDecl.
 0144          object a = d0 is ModuleDecl ? ((ModuleDecl)d0).Dereference() : d0;
 0145          object b = d1 is ModuleDecl ? ((ModuleDecl)d1).Dereference() : d1;
 0146          return a == b;
 0147        }
 148
 0149        public int GetHashCode(TopLevelDecl d) {
 0150          object a = d is ModuleDecl ? ((ModuleDecl)d).Dereference() : d;
 0151          return a.GetHashCode();
 0152        }
 153      }
 154
 155      public override string WhatKind {
 0156        get { return Pool.First().WhatKind; }
 157      }
 158
 0159      readonly ISet<TopLevelDecl> Pool = new HashSet<TopLevelDecl>();
 160
 161      ISet<TopLevelDecl> IAmbiguousThing<TopLevelDecl>.Pool {
 0162        get { return Pool; }
 163      }
 164
 165      private AmbiguousTopLevelDecl(ModuleDefinition m, string name, ISet<TopLevelDecl> pool)
 0166        : base(pool.First().RangeToken, new Name(pool.First().RangeToken, name), m, new List<TypeParameter>(), null, fal
 167        Contract.Requires(name != null);
 168        Contract.Requires(pool != null && 2 <= pool.Count);
 0169        Pool = pool;
 0170      }
 171
 0172      public string ModuleNames() {
 0173        return AmbiguousThingHelper<TopLevelDecl>.ModuleNames(this, d => d.EnclosingModuleDefinition.Name);
 0174      }
 175    }
 176
 177    class AmbiguousMemberDecl : MemberDecl, IAmbiguousThing<MemberDecl> // only used with "classes"
 178    {
 0179      public static MemberDecl Create(ModuleDefinition m, MemberDecl a, MemberDecl b) {
 180        ISet<MemberDecl> s;
 0181        var t = AmbiguousThingHelper<MemberDecl>.Create(m, a, b, new Eq(), out s);
 0182        return t ?? new AmbiguousMemberDecl(m, AmbiguousThingHelper<MemberDecl>.Name(s, member => member.Name), s);
 0183      }
 184
 185      class Eq : IEqualityComparer<MemberDecl> {
 0186        public bool Equals(MemberDecl d0, MemberDecl d1) {
 0187          return d0 == d1;
 0188        }
 189
 0190        public int GetHashCode(MemberDecl d) {
 0191          return d.GetHashCode();
 0192        }
 193      }
 194
 195      public override string WhatKind {
 0196        get { return Pool.First().WhatKind; }
 197      }
 198
 0199      readonly ISet<MemberDecl> Pool = new HashSet<MemberDecl>();
 200
 201      ISet<MemberDecl> IAmbiguousThing<MemberDecl>.Pool {
 0202        get { return Pool; }
 203      }
 204
 205      private AmbiguousMemberDecl(ModuleDefinition m, string name, ISet<MemberDecl> pool)
 0206        : base(pool.First().RangeToken, new Name(pool.First().RangeToken, name), true, pool.First().IsGhost, null, false
 207        Contract.Requires(name != null);
 208        Contract.Requires(pool != null && 2 <= pool.Count);
 0209        Pool = pool;
 0210      }
 211
 0212      public string ModuleNames() {
 0213        return AmbiguousThingHelper<MemberDecl>.ModuleNames(this, d => d.EnclosingClass.EnclosingModuleDefinition.Name);
 0214      }
 215    }
 216
 306217    readonly HashSet<RevealableTypeDecl> revealableTypes = new HashSet<RevealableTypeDecl>();
 218    //types that have been seen by the resolver - used for constraining type inference during exports
 219
 306220    public readonly Dictionary<TopLevelDeclWithMembers, Dictionary<string, MemberDecl>> classMembers =
 306221      new Dictionary<TopLevelDeclWithMembers, Dictionary<string, MemberDecl>>();
 222
 223    enum ValuetypeVariety {
 224      Bool = 0,
 225      Int,
 226      Real,
 227      BigOrdinal,
 228      Bitvector,
 229      Map,
 230      IMap,
 231      None
 232    } // note, these are ordered, so they can be used as indices into valuetypeDecls
 233
 234    internal readonly ValuetypeDecl[] valuetypeDecls;
 235    private Dictionary<TypeParameter, Type> SelfTypeSubstitution;
 306236    readonly Graph<ModuleDecl> dependencies = new Graph<ModuleDecl>();
 306237    private ModuleSignature systemNameInfo = null;
 306238    private bool useCompileSignatures = false;
 239
 240    private List<IRewriter> rewriters;
 241    private RefinementTransformer refinementTransformer;
 242
 0243    public Resolver(DafnyOptions options) {
 0244      Options = options;
 0245    }
 246
 612247    public Resolver(Program prog) {
 306248      Options = prog.Options;
 249
 306250      allTypeParameters = new Scope<TypeParameter>(Options);
 306251      scope = new Scope<IVariable>(Options);
 306252      enclosingStatementLabels = new Scope<Statement>(Options);
 306253      DominatingStatementLabels = new Scope<Label>(Options);
 254
 255      Contract.Requires(prog != null);
 256
 306257      builtIns = prog.BuiltIns;
 306258      reporter = prog.Reporter;
 259
 260      // Map#Items relies on the two destructors for 2-tuples
 306261      builtIns.TupleType(Token.NoToken, 2, true);
 262      // Several methods and fields rely on 1-argument arrow types
 306263      builtIns.CreateArrowTypeDecl(1);
 264
 306265      valuetypeDecls = new ValuetypeDecl[] {
 16589266        new ValuetypeDecl("bool", builtIns.SystemModule, t => t.IsBoolType, typeArgs => Type.Bool),
 16589267        new ValuetypeDecl("int", builtIns.SystemModule, t => t.IsNumericBased(Type.NumericPersuasion.Int), typeArgs => T
 16589268        new ValuetypeDecl("real", builtIns.SystemModule, t => t.IsNumericBased(Type.NumericPersuasion.Real), typeArgs =>
 15689269        new ValuetypeDecl("ORDINAL", builtIns.SystemModule, t => t.IsBigOrdinalType, typeArgs => Type.BigOrdinal),
 15689270        new ValuetypeDecl("_bv", builtIns.SystemModule, t => t.IsBitVectorType, null), // "_bv" represents a family of c
 306271        new ValuetypeDecl("map", builtIns.SystemModule,
 306272          new List<TypeParameter.TPVarianceSyntax>() { TypeParameter.TPVarianceSyntax.Covariant_Strict , TypeParameter.T
 15689273          t => t.IsMapType, typeArgs => new MapType(true, typeArgs[0], typeArgs[1])),
 306274        new ValuetypeDecl("imap", builtIns.SystemModule,
 306275          new List<TypeParameter.TPVarianceSyntax>() { TypeParameter.TPVarianceSyntax.Covariant_Permissive , TypeParamet
 15469276          t => t.IsIMapType, typeArgs => new MapType(false, typeArgs[0], typeArgs[1]))
 306277      };
 306278      builtIns.SystemModule.TopLevelDecls.AddRange(valuetypeDecls);
 279      // Resolution error handling relies on being able to get to the 0-tuple declaration
 306280      builtIns.TupleType(Token.NoToken, 0, true);
 281
 282      // Populate the members of the basic types
 283
 3366284      void AddMember(MemberDecl member, ValuetypeVariety valuetypeVariety) {
 3366285        var enclosingType = valuetypeDecls[(int)valuetypeVariety];
 3366286        member.EnclosingClass = enclosingType;
 3366287        member.AddVisibilityScope(prog.BuiltIns.SystemModule.VisibilityScope, false);
 3366288        enclosingType.Members.Add(member.Name, member);
 3366289      }
 290
 306291      var floor = new SpecialField(RangeToken.NoToken, "Floor", SpecialField.ID.Floor, null, false, false, false, Type.I
 306292      AddMember(floor, ValuetypeVariety.Real);
 293
 306294      var isLimit = new SpecialField(RangeToken.NoToken, "IsLimit", SpecialField.ID.IsLimit, null, false, false, false, 
 306295      AddMember(isLimit, ValuetypeVariety.BigOrdinal);
 296
 306297      var isSucc = new SpecialField(RangeToken.NoToken, "IsSucc", SpecialField.ID.IsSucc, null, false, false, false, Typ
 306298      AddMember(isSucc, ValuetypeVariety.BigOrdinal);
 299
 306300      var limitOffset = new SpecialField(RangeToken.NoToken, "Offset", SpecialField.ID.Offset, null, false, false, false
 306301      AddMember(limitOffset, ValuetypeVariety.BigOrdinal);
 306302      builtIns.ORDINAL_Offset = limitOffset;
 303
 306304      var isNat = new SpecialField(RangeToken.NoToken, "IsNat", SpecialField.ID.IsNat, null, false, false, false, Type.B
 306305      AddMember(isNat, ValuetypeVariety.BigOrdinal);
 306
 307      // Add "Keys", "Values", and "Items" to map, imap
 2754308      foreach (var typeVariety in new[] { ValuetypeVariety.Map, ValuetypeVariety.IMap }) {
 612309        var vtd = valuetypeDecls[(int)typeVariety];
 612310        var isFinite = typeVariety == ValuetypeVariety.Map;
 311
 612312        var r = new SetType(isFinite, new UserDefinedType(vtd.TypeArgs[0]));
 612313        var keys = new SpecialField(RangeToken.NoToken, "Keys", SpecialField.ID.Keys, null, false, false, false, r, null
 314
 612315        r = new SetType(isFinite, new UserDefinedType(vtd.TypeArgs[1]));
 612316        var values = new SpecialField(RangeToken.NoToken, "Values", SpecialField.ID.Values, null, false, false, false, r
 317
 1836318        var gt = vtd.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp));
 612319        var dt = builtIns.TupleType(Token.NoToken, 2, true);
 612320        var tupleType = new UserDefinedType(Token.NoToken, dt.Name, dt, gt);
 612321        r = new SetType(isFinite, tupleType);
 612322        var items = new SpecialField(RangeToken.NoToken, "Items", SpecialField.ID.Items, null, false, false, false, r, n
 323
 7344324        foreach (var memb in new[] { keys, values, items }) {
 1836325          AddMember(memb, typeVariety);
 1836326        }
 612327      }
 328
 329      // The result type of the following bitvector methods is the type of the bitvector itself. However, we're represen
 330      // a family of types rolled up in one ValuetypeDecl. Therefore, we use the special SelfType as the result type.
 306331      AddRotateMember(valuetypeDecls[(int)ValuetypeVariety.Bitvector], "RotateLeft", new SelfType());
 306332      AddRotateMember(valuetypeDecls[(int)ValuetypeVariety.Bitvector], "RotateRight", new SelfType());
 306333    }
 334
 612335    public void AddRotateMember(ValuetypeDecl enclosingType, string name, Type resultType) {
 612336      var formals = new List<Formal> { new Formal(Token.NoToken, "w", Type.Nat(), true, false, null, false) };
 612337      var rotateMember = new SpecialFunction(RangeToken.NoToken, name, builtIns.SystemModule, false, false,
 612338        new List<TypeParameter>(), formals, resultType,
 612339        new List<AttributedExpression>(), new List<FrameExpression>(), new List<AttributedExpression>(),
 612340        new Specification<Expression>(new List<Expression>(), null), null, null, null);
 612341      rotateMember.EnclosingClass = enclosingType;
 612342      rotateMember.AddVisibilityScope(builtIns.SystemModule.VisibilityScope, false);
 612343      enclosingType.Members.Add(name, rotateMember);
 612344    }
 345
 346    [ContractInvariantMethod]
 0347    void ObjectInvariant() {
 348      Contract.Invariant(builtIns != null);
 349      Contract.Invariant(cce.NonNullElements(dependencies.GetVertices()));
 350      Contract.Invariant(cce.NonNullDictionaryAndValues(classMembers) && Contract.ForAll(classMembers.Values, v => cce.N
 0351    }
 352
 560353    public ValuetypeDecl AsValuetypeDecl(Type t) {
 354      Contract.Requires(t != null);
 7150355      foreach (var vtd in valuetypeDecls) {
 2570356        if (vtd.IsThisType(t)) {
 560357          return vtd;
 358        }
 1450359      }
 0360      return null;
 560361    }
 362
 363    /// <summary>
 364    /// Check that now two modules that are being compiled have the same CompileName.
 365    ///
 366    /// This could happen if they are given the same name using the 'extern' declaration modifier.
 367    /// </summary>
 368    /// <param name="prog">The Dafny program being compiled.</param>
 276369    void CheckDupModuleNames(Program prog) {
 370      // Check that none of the modules have the same CompileName.
 276371      Dictionary<string, ModuleDefinition> compileNameMap = new Dictionary<string, ModuleDefinition>();
 2484372      foreach (ModuleDefinition m in prog.CompileModules) {
 552373        var compileIt = true;
 552374        Attributes.ContainsBool(m.Attributes, "compile", ref compileIt);
 552375        if (m.IsAbstract || !compileIt) {
 376          // the purpose of an abstract module is to skip compilation
 0377          continue;
 378        }
 552379        string compileName = m.GetCompileName(Options);
 380        ModuleDefinition priorModDef;
 552381        if (compileNameMap.TryGetValue(compileName, out priorModDef)) {
 0382          reporter.Error(MessageSource.Resolver, m.tok,
 0383            "modules '{0}' and '{1}' both have CompileName '{2}'",
 0384            priorModDef.tok.val, m.tok.val, compileName);
 552385        } else {
 552386          compileNameMap.Add(compileName, m);
 552387        }
 552388      }
 276389    }
 390
 306391    public void ResolveProgram(Program prog) {
 392      Contract.Requires(prog != null);
 306393      Type.ResetScopes();
 394
 306395      Type.EnableScopes();
 396      // For the formatter, we ensure we take snapshots of the PrefixNamedModules
 397      // and topleveldecls
 306398      prog.DefaultModuleDef.PreResolveSnapshotForFormatter();
 306399      var origErrorCount = reporter.ErrorCount; //TODO: This is used further below, but not in the >0 comparisons in the
 306400      var bindings = new ModuleBindings(null);
 306401      var b = BindModuleNames(prog.DefaultModuleDef, bindings);
 306402      bindings.BindName(prog.DefaultModule.Name, prog.DefaultModule, b);
 306403      if (reporter.ErrorCount > 0) {
 0404        return;
 405      } // if there were errors, then the implict ModuleBindings data structure invariant
 406
 407      // is violated, so Processing dependencies will not succeed.
 306408      ProcessDependencies(prog.DefaultModule, b, dependencies);
 409      // check for cycles in the import graph
 918410      foreach (var cycle in dependencies.AllCycles()) {
 0411        ReportCycleError(cycle, m => m.tok,
 0412          m => (m is AliasModuleDecl ? "import " : "module ") + m.Name,
 0413          "module definition contains a cycle (note: parent modules implicitly depend on submodules)");
 0414      }
 415
 306416      if (reporter.ErrorCount > 0) {
 0417        return;
 418      } // give up on trying to resolve anything else
 419
 420      // fill in module heights
 306421      List<ModuleDecl> sortedDecls = dependencies.TopologicallySortedComponents();
 306422      int h = 0;
 1836423      foreach (ModuleDecl md in sortedDecls) {
 306424        md.Height = h;
 612425        if (md is LiteralModuleDecl) {
 306426          var mdef = ((LiteralModuleDecl)md).ModuleDef;
 306427          mdef.Height = h;
 306428          prog.ModuleSigs.Add(mdef, null);
 306429        }
 306430        h++;
 306431      }
 432
 306433      rewriters = new List<IRewriter>();
 434
 306435      if (Options.AuditProgram) {
 0436        rewriters.Add(new Auditor.Auditor(reporter));
 0437      }
 438
 306439      refinementTransformer = new RefinementTransformer(prog);
 306440      rewriters.Add(refinementTransformer);
 612441      if (!Options.VerifyAllModules) {
 306442        rewriters.Add(new IncludedLemmaBodyRemover(prog, reporter));
 306443      }
 306444      rewriters.Add(new AutoContractsRewriter(reporter, builtIns));
 306445      rewriters.Add(new OpaqueMemberRewriter(this.reporter));
 306446      rewriters.Add(new AutoReqFunctionRewriter(this.reporter, this.builtIns));
 306447      rewriters.Add(new TimeLimitRewriter(reporter));
 306448      rewriters.Add(new ForallStmtRewriter(reporter));
 306449      rewriters.Add(new ProvideRevealAllRewriter(this.reporter));
 306450      rewriters.Add(new MatchFlattener(this.reporter, defaultTempVarIdGenerator));
 451
 612452      if (Options.AutoTriggers) {
 306453        rewriters.Add(new QuantifierSplittingRewriter(reporter));
 306454        rewriters.Add(new TriggerGeneratingRewriter(reporter));
 306455      }
 456
 306457      if (Options.TestContracts != DafnyOptions.ContractTestingMode.None) {
 0458        rewriters.Add(new ExpectContracts(reporter));
 0459      }
 460
 306461      if (Options.RunAllTests) {
 0462        rewriters.Add(new RunAllTestsMainMethod(reporter));
 0463      }
 464
 306465      rewriters.Add(new InductionRewriter(reporter));
 306466      rewriters.Add(new PrintEffectEnforcement(reporter));
 306467      rewriters.Add(new BitvectorOptimization(reporter));
 468
 306469      if (Options.DisallowConstructorCaseWithoutParentheses) {
 0470        rewriters.Add(new ConstructorWarning(reporter));
 0471      }
 306472      rewriters.Add(new LocalLinter(reporter));
 306473      rewriters.Add(new PrecedenceLinter(reporter));
 474
 2754475      foreach (var plugin in Options.Plugins) {
 612476        rewriters.AddRange(plugin.GetRewriters(reporter));
 612477      }
 478
 306479      systemNameInfo = RegisterTopLevelDecls(prog.BuiltIns.SystemModule, false);
 306480      prog.CompileModules.Add(prog.BuiltIns.SystemModule);
 306481      RevealAllInScope(prog.BuiltIns.SystemModule.TopLevelDecls, systemNameInfo.VisibilityScope);
 306482      ResolveValuetypeDecls();
 483      // The SystemModule is constructed with all its members already being resolved. Except for
 484      // the non-null type corresponding to class types.  They are resolved here:
 306485      var systemModuleClassesWithNonNullTypes =
 6246486        prog.BuiltIns.SystemModule.TopLevelDecls.Where(d => (d as ClassDecl)?.NonNullTypeDecl != null).ToList();
 2754487      foreach (var cl in systemModuleClassesWithNonNullTypes) {
 612488        var d = ((ClassDecl)cl).NonNullTypeDecl;
 612489        allTypeParameters.PushMarker();
 612490        ResolveTypeParameters(d.TypeArgs, true, d);
 612491        ResolveType(d.tok, d.Rhs, d, ResolveTypeOptionEnum.AllowPrefix, d.TypeArgs);
 612492        allTypeParameters.PopMarker();
 612493      }
 306494      ResolveTopLevelDecls_Core(ModuleDefinition.AllDeclarationsAndNonNullTypeDecls(systemModuleClassesWithNonNullTypes)
 306495        new Graph<IndDatatypeDecl>(), new Graph<CoDatatypeDecl>(), prog.BuiltIns.SystemModule.Name);
 496
 15606497      foreach (var rewriter in rewriters) {
 4896498        rewriter.PreResolve(prog);
 4896499      }
 500
 306501      var compilationModuleClones = new Dictionary<ModuleDefinition, ModuleDefinition>();
 1836502      foreach (var decl in sortedDecls) {
 612503        if (decl is LiteralModuleDecl) {
 504          // The declaration is a literal module, so it has members and such that we need
 505          // to resolve. First we do refinement transformation. Then we construct the signature
 506          // of the module. This is the public, externally visible signature. Then we add in
 507          // everything that the system defines, as well as any "import" (i.e. "opened" modules)
 508          // directives (currently not supported, but this is where we would do it.) This signature,
 509          // which is only used while resolving the members of the module is stored in the (basically)
 510          // global variable moduleInfo. Then the signatures of the module members are resolved, followed
 511          // by the bodies.
 306512          var literalDecl = (LiteralModuleDecl)decl;
 306513          var m = literalDecl.ModuleDef;
 514
 306515          var errorCount = reporter.ErrorCount;
 306516          if (m.RefinementQId != null) {
 0517            ModuleDecl md = ResolveModuleQualifiedId(m.RefinementQId.Root, m.RefinementQId, reporter);
 0518            m.RefinementQId.Set(md); // If module is not found, md is null and an error message has been emitted
 0519          }
 520
 15606521          foreach (var rewriter in rewriters) {
 4896522            rewriter.PreResolve(m);
 4896523          }
 524
 306525          literalDecl.Signature = RegisterTopLevelDecls(m, true);
 306526          literalDecl.Signature.Refines = refinementTransformer.RefinedSig;
 527
 306528          var sig = literalDecl.Signature;
 529          // set up environment
 306530          var preResolveErrorCount = reporter.ErrorCount;
 531
 306532          ResolveModuleExport(literalDecl, sig);
 306533          var good = ResolveModuleDefinition(m, sig);
 534
 582535          if (good && reporter.ErrorCount == preResolveErrorCount) {
 536            // Check that the module export gives a self-contained view of the module.
 276537            CheckModuleExportConsistency(m);
 276538          }
 539
 306540          var tempVis = new VisibilityScope();
 306541          tempVis.Augment(sig.VisibilityScope);
 306542          tempVis.Augment(systemNameInfo.VisibilityScope);
 306543          Type.PushScope(tempVis);
 544
 306545          prog.ModuleSigs[m] = sig;
 546
 14226547          foreach (var rewriter in rewriters) {
 4476548            if (!good || reporter.ErrorCount != preResolveErrorCount) {
 30549              break;
 550            }
 4416551            rewriter.PostResolveIntermediate(m);
 4416552          }
 582553          if (good && reporter.ErrorCount == errorCount) {
 276554            m.SuccessfullyResolved = true;
 276555          }
 306556          Type.PopScope(tempVis);
 557
 582558          if (reporter.ErrorCount == errorCount && !m.IsAbstract) {
 559            // compilation should only proceed if everything is good, including the signature (which preResolveErrorCoun
 276560            CompilationCloner cloner = new CompilationCloner(compilationModuleClones);
 276561            var nw = cloner.CloneModuleDefinition(m, new Name(m.NameNode.RangeToken, m.GetCompileName(Options) + "_Compi
 276562            compilationModuleClones.Add(m, nw);
 276563            var oldErrorsOnly = reporter.ErrorsOnly;
 276564            reporter.ErrorsOnly = true; // turn off warning reporting for the clone
 565            // Next, compute the compile signature
 276566            Contract.Assert(!useCompileSignatures);
 276567            useCompileSignatures = true; // set Resolver-global flag to indicate that Signatures should be followed to t
 276568            Type.DisableScopes();
 276569            var compileSig = RegisterTopLevelDecls(nw, true);
 276570            compileSig.Refines = refinementTransformer.RefinedSig;
 276571            sig.CompileSignature = compileSig;
 828572            foreach (var exportDecl in sig.ExportSets.Values) {
 0573              exportDecl.Signature.CompileSignature = cloner.CloneModuleSignature(exportDecl.Signature, compileSig);
 0574            }
 575            // Now we're ready to resolve the cloned module definition, using the compile signature
 576
 276577            ResolveModuleDefinition(nw, compileSig);
 578
 14076579            foreach (var rewriter in rewriters) {
 4416580              rewriter.PostCompileCloneAndResolve(nw);
 4416581            }
 582
 276583            prog.CompileModules.Add(nw);
 276584            useCompileSignatures = false; // reset the flag
 276585            Type.EnableScopes();
 276586            reporter.ErrorsOnly = oldErrorsOnly;
 276587          }
 306588        } else if (decl is AliasModuleDecl alias) {
 589          // resolve the path
 590          ModuleSignature p;
 0591          if (ResolveExport(alias, alias.EnclosingModuleDefinition, alias.TargetQId, alias.Exports, out p, reporter)) {
 0592            if (alias.Signature == null) {
 0593              alias.Signature = p;
 0594            }
 0595          } else {
 0596            alias.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature
 0597          }
 0598        } else if (decl is AbstractModuleDecl abs) {
 599          ModuleSignature p;
 0600          if (ResolveExport(abs, abs.EnclosingModuleDefinition, abs.QId, abs.Exports, out p, reporter)) {
 0601            abs.OriginalSignature = p;
 0602            abs.Signature = MakeAbstractSignature(p, abs.FullSanitizedName, abs.Height, prog.ModuleSigs, compilationModu
 0603          } else {
 0604            abs.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature
 0605          }
 0606        } else if (decl is ModuleExportDecl) {
 0607          ((ModuleExportDecl)decl).SetupDefaultSignature();
 608
 0609          Contract.Assert(decl.Signature != null);
 0610          Contract.Assert(decl.Signature.VisibilityScope != null);
 611
 0612        } else {
 0613          Contract.Assert(false); // Unknown kind of ModuleDecl
 0614        }
 615
 306616        Contract.Assert(decl.Signature != null);
 306617      }
 618
 336619      if (reporter.ErrorCount != origErrorCount) {
 620        // do nothing else
 30621        return;
 622      }
 623
 624      // compute IsRecursive bit for mutually recursive functions and methods
 1656625      foreach (var module in prog.Modules()) {
 8097626        foreach (var clbl in ModuleDefinition.AllCallables(module.TopLevelDecls)) {
 2423627          if (clbl is Function) {
 0628            var fn = (Function)clbl;
 0629            if (!fn.IsRecursive) { // note, self-recursion has already been determined
 0630              int n = module.CallGraph.GetSCCSize(fn);
 0631              if (2 <= n) {
 632                // the function is mutually recursive (note, the SCC does not determine self recursion)
 0633                fn.IsRecursive = true;
 0634              }
 0635            }
 0636            if (fn.IsRecursive && fn is ExtremePredicate) {
 637              // this means the corresponding prefix predicate is also recursive
 0638              var prefixPred = ((ExtremePredicate)fn).PrefixPredicate;
 0639              if (prefixPred != null) {
 0640                prefixPred.IsRecursive = true;
 0641              }
 0642            }
 2423643          } else {
 2423644            var m = (Method)clbl;
 4846645            if (!m.IsRecursive) {
 646              // note, self-recursion has already been determined
 2423647              int n = module.CallGraph.GetSCCSize(m);
 2423648              if (2 <= n) {
 649                // the function is mutually recursive (note, the SCC does not determine self recursion)
 0650              }
 2423651            }
 2423652          }
 2423653        }
 654
 14076655        foreach (var rewriter in rewriters) {
 4416656          rewriter.PostCyclicityResolve(module);
 4416657        }
 276658      }
 659
 660      // fill in default decreases clauses:  for functions and methods, and for loops
 276661      new InferDecreasesClause(this).FillInDefaultDecreasesClauses(prog);
 1656662      foreach (var module in prog.Modules()) {
 8097663        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 2423664          Statement body = null;
 4846665          if (clbl is Method) {
 2423666            body = ((Method)clbl).Body;
 2423667          } else if (clbl is IteratorDecl) {
 0668            body = ((IteratorDecl)clbl).Body;
 0669          }
 670
 4846671          if (body != null) {
 2423672            var c = new FillInDefaultLoopDecreases_Visitor(this, clbl);
 2423673            c.Visit(body);
 2423674          }
 2423675        }
 276676      }
 677
 1656678      foreach (var module in prog.Modules()) {
 828679        foreach (var iter in ModuleDefinition.AllIteratorDecls(module.TopLevelDecls)) {
 0680          reporter.Info(MessageSource.Resolver, iter.tok, Printer.IteratorClassToString(Reporter.Options, iter));
 0681        }
 276682      }
 683
 1656684      foreach (var module in prog.Modules()) {
 14076685        foreach (var rewriter in rewriters) {
 4416686          rewriter.PostDecreasesResolve(module);
 4416687        }
 276688      }
 689
 690      // fill in other additional information
 1656691      foreach (var module in prog.Modules()) {
 8097692        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 2423693          Statement body = null;
 2423694          if (clbl is ExtremeLemma) {
 0695            body = ((ExtremeLemma)clbl).PrefixLemma.Body;
 4846696          } else if (clbl is Method) {
 2423697            body = ((Method)clbl).Body;
 2423698          } else if (clbl is IteratorDecl) {
 0699            body = ((IteratorDecl)clbl).Body;
 0700          }
 701
 4846702          if (body != null) {
 2423703            var c = new ReportOtherAdditionalInformation_Visitor(this);
 2423704            c.Visit(body);
 2423705          }
 2423706        }
 276707      }
 708
 709      // Determine, for each function, whether someone tries to adjust its fuel parameter
 1656710      foreach (var module in prog.Modules()) {
 276711        CheckForFuelAdjustments(module.tok, module.Attributes, module);
 8097712        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 2423713          Statement body = null;
 4846714          if (clbl is Method) {
 2423715            body = ((Method)clbl).Body;
 2423716            CheckForFuelAdjustments(clbl.Tok, ((Method)clbl).Attributes, module);
 2423717          } else if (clbl is IteratorDecl) {
 0718            body = ((IteratorDecl)clbl).Body;
 0719            CheckForFuelAdjustments(clbl.Tok, ((IteratorDecl)clbl).Attributes, module);
 0720          } else if (clbl is Function) {
 0721            CheckForFuelAdjustments(clbl.Tok, ((Function)clbl).Attributes, module);
 0722            var c = new FuelAdjustment_Visitor(this);
 0723            var bodyExpr = ((Function)clbl).Body;
 0724            if (bodyExpr != null) {
 0725              c.Visit(bodyExpr, new FuelAdjustment_Context(module));
 0726            }
 0727          }
 728
 4846729          if (body != null) {
 2423730            var c = new FuelAdjustment_Visitor(this);
 2423731            c.Visit(body, new FuelAdjustment_Context(module));
 2423732          }
 2423733        }
 276734      }
 735
 276736      Type.DisableScopes();
 276737      CheckDupModuleNames(prog);
 738
 1656739      foreach (var module in prog.Modules()) {
 14076740        foreach (var rewriter in rewriters) {
 4416741          rewriter.PostResolve(module);
 4416742        }
 276743      }
 744
 14076745      foreach (var rewriter in rewriters) {
 4416746        rewriter.PostResolve(prog);
 4416747      }
 306748    }
 749
 750
 751
 306752    private void ResolveValuetypeDecls() {
 306753      moduleInfo = systemNameInfo;
 7344754      foreach (var valueTypeDecl in valuetypeDecls) {
 18360755        foreach (var kv in valueTypeDecl.Members) {
 4590756          if (kv.Value is Function function) {
 612757            ResolveFunctionSignature(function);
 612758            CallGraphBuilder.VisitFunction(function, reporter);
 3978759          } else if (kv.Value is Method method) {
 0760            ResolveMethodSignature(method);
 0761            CallGraphBuilder.VisitMethod(method, reporter);
 0762          }
 3978763        }
 2142764      }
 306765    }
 766
 767    /// <summary>
 768    /// Resolves the module definition.
 769    /// A return code of "false" is an indication of an error that may or may not have
 770    /// been reported in an error message. So, in order to figure out if m was successfully
 771    /// resolved, a caller has to check for both a change in error count and a "false"
 772    /// return value.
 773    /// </summary>
 582774    private bool ResolveModuleDefinition(ModuleDefinition m, ModuleSignature sig, bool isAnExport = false) {
 775      Contract.Requires(AllTypeConstraints.Count == 0);
 776      Contract.Ensures(AllTypeConstraints.Count == 0);
 777
 582778      sig.VisibilityScope.Augment(systemNameInfo.VisibilityScope);
 779      // make sure all imported modules were successfully resolved
 5073780      foreach (var d in m.TopLevelDecls) {
 1109781        if (d is AliasModuleDecl || d is AbstractModuleDecl) {
 782          ModuleSignature importSig;
 0783          if (d is AliasModuleDecl) {
 0784            var alias = (AliasModuleDecl)d;
 0785            importSig = alias.TargetQId.Root != null ? alias.TargetQId.Root.Signature : alias.Signature;
 0786          } else {
 0787            importSig = ((AbstractModuleDecl)d).OriginalSignature;
 0788          }
 789
 0790          if (importSig.ModuleDef == null || !importSig.ModuleDef.SuccessfullyResolved) {
 0791            if (!m.IsEssentiallyEmptyModuleBody()) {
 792              // say something only if this will cause any testing to be omitted
 0793              reporter.Error(MessageSource.Resolver, d,
 0794                "not resolving module '{0}' because there were errors in resolving its import '{1}'", m.Name, d.Name);
 0795            }
 796
 0797            return false;
 798          }
 1109799        } else if (d is LiteralModuleDecl) {
 0800          var nested = (LiteralModuleDecl)d;
 0801          if (!nested.ModuleDef.SuccessfullyResolved) {
 0802            if (!m.IsEssentiallyEmptyModuleBody()) {
 803              // say something only if this will cause any testing to be omitted
 0804              reporter.Error(MessageSource.Resolver, nested,
 0805                "not resolving module '{0}' because there were errors in resolving its nested module '{1}'", m.Name,
 0806                nested.Name);
 0807            }
 808
 0809            return false;
 810          }
 0811        }
 1109812      }
 813
 814      // resolve
 582815      var oldModuleInfo = moduleInfo;
 582816      moduleInfo = MergeSignature(sig, systemNameInfo);
 582817      Type.PushScope(moduleInfo.VisibilityScope);
 582818      ResolveOpenedImports(moduleInfo, m, useCompileSignatures, this); // opened imports do not persist
 582819      var datatypeDependencies = new Graph<IndDatatypeDecl>();
 582820      var codatatypeDependencies = new Graph<CoDatatypeDecl>();
 582821      var allDeclarations = ModuleDefinition.AllDeclarationsAndNonNullTypeDecls(m.TopLevelDecls).ToList();
 582822      int prevErrorCount = reporter.Count(ErrorLevel.Error);
 582823      ResolveTopLevelDecls_Signatures(m, sig, allDeclarations, datatypeDependencies, codatatypeDependencies);
 582824      Contract.Assert(AllTypeConstraints.Count == 0); // signature resolution does not add any type constraints
 825
 582826      scope.PushMarker();
 582827      scope.AllowInstance = false;
 582828      ResolveAttributes(m, new ResolutionContext(new NoContext(m.EnclosingModule), false), true); // Must follow Resolve
 582829      scope.PopMarker();
 830
 1164831      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 582832        ResolveTopLevelDecls_Core(allDeclarations, datatypeDependencies, codatatypeDependencies, m.Name, isAnExport);
 582833      }
 834
 582835      Type.PopScope(moduleInfo.VisibilityScope);
 582836      moduleInfo = oldModuleInfo;
 582837      return true;
 582838    }
 839
 840    // Resolve the exports and detect cycles.
 306841    private void ResolveModuleExport(LiteralModuleDecl literalDecl, ModuleSignature sig) {
 306842      ModuleDefinition m = literalDecl.ModuleDef;
 306843      literalDecl.DefaultExport = sig;
 306844      Graph<ModuleExportDecl> exportDependencies = new Graph<ModuleExportDecl>();
 2739845      foreach (TopLevelDecl toplevel in m.TopLevelDecls) {
 607846        if (toplevel is ModuleExportDecl) {
 0847          ModuleExportDecl d = (ModuleExportDecl)toplevel;
 0848          exportDependencies.AddVertex(d);
 0849          foreach (IToken s in d.Extends) {
 850            ModuleExportDecl extend;
 0851            if (sig.ExportSets.TryGetValue(s.val, out extend)) {
 0852              d.ExtendDecls.Add(extend);
 0853              exportDependencies.AddEdge(d, extend);
 0854            } else {
 0855              reporter.Error(MessageSource.Resolver, s, s.val + " must be an export of " + m.Name + " to be extended");
 0856            }
 0857          }
 0858        }
 607859      }
 860
 861      // detect cycles in the extend
 306862      var cycleError = false;
 918863      foreach (var cycle in exportDependencies.AllCycles()) {
 0864        ReportCycleError(cycle, m => m.tok, m => m.Name, "module export contains a cycle");
 0865        cycleError = true;
 0866      }
 867
 306868      if (cycleError) {
 0869        return;
 870      } // give up on trying to resolve anything else
 871
 872      // fill in the exports for the extends.
 306873      List<ModuleExportDecl> sortedExportDecls = exportDependencies.TopologicallySortedComponents();
 306874      ModuleExportDecl defaultExport = null;
 875      TopLevelDecl defaultClass;
 876
 306877      sig.TopLevels.TryGetValue("_default", out defaultClass);
 306878      Contract.Assert(defaultClass is ClassDecl);
 306879      Contract.Assert(((ClassDecl)defaultClass).IsDefaultClass);
 306880      defaultClass.AddVisibilityScope(m.VisibilityScope, true);
 881
 918882      foreach (var d in sortedExportDecls) {
 883
 0884        defaultClass.AddVisibilityScope(d.ThisScope, true);
 885
 0886        foreach (var eexports in d.ExtendDecls.Select(e => e.Exports)) {
 0887          d.Exports.AddRange(eexports);
 0888        }
 889
 0890        if (d.ExtendDecls.Count == 0 && d.Exports.Count == 0) {
 891          // This is an empty export.  This is allowed, but unusual.  It could pop up, for example, if
 892          // someone temporary comments out everything that the export set provides/reveals.  However,
 893          // if the name of the export set coincides with something else that's declared at the top
 894          // level of the module, then this export declaration is more likely an error--the user probably
 895          // forgot the "provides" or "reveals" keyword.
 896          Dictionary<string, MemberDecl> members;
 897          MemberDecl member;
 898          // Top-level functions and methods are actually recorded as members of the _default class.  We look up the
 899          // export-set name there.  If the export-set name happens to coincide with some other top-level declaration,
 900          // then an error will already have been produced ("duplicate name of top-level declaration").
 0901          if (classMembers.TryGetValue((ClassDecl)defaultClass, out members) &&
 0902              members.TryGetValue(d.Name, out member)) {
 0903            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, d.tok,
 0904              "note, this export set is empty (did you perhaps forget the 'provides' or 'reveals' keyword?)");
 0905          }
 0906        }
 907
 0908        foreach (ExportSignature export in d.Exports) {
 909
 910          // check to see if it is a datatype or a member or
 911          // static function or method in the enclosing module or its imports
 912          TopLevelDecl tdecl;
 913          MemberDecl member;
 914          TopLevelDecl cldecl;
 915
 0916          Declaration decl = null;
 0917          string name = export.Id;
 918
 0919          if (export.ClassId != null) {
 0920            if (!sig.TopLevels.TryGetValue(export.ClassId, out cldecl)) {
 0921              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a top-level type declaration",
 0922                export.ClassId);
 0923              continue;
 924            }
 925
 0926            if (cldecl is ClassDecl && ((ClassDecl)cldecl).NonNullTypeDecl != null) {
 927              // cldecl is a possibly-null type (syntactically given with a question mark at the end)
 0928              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a type that can declare members",
 0929                export.ClassId);
 0930              continue;
 931            }
 932
 0933            if (cldecl is NonNullTypeDecl) {
 934              // cldecl was given syntactically like the name of a class, but here it's referring to the corresponding n
 0935              cldecl = cldecl.ViewAsClass;
 0936            }
 937
 0938            var mt = cldecl as TopLevelDeclWithMembers;
 0939            if (mt == null) {
 0940              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a type that can declare members",
 0941                export.ClassId);
 0942              continue;
 943            }
 944
 0945            var lmem = mt.Members.FirstOrDefault(l => l.Name == export.Id);
 0946            if (lmem == null) {
 0947              reporter.Error(MessageSource.Resolver, export.Tok, "No member '{0}' found in type '{1}'", export.Id,
 0948                export.ClassId);
 0949              continue;
 950            }
 951
 0952            decl = lmem;
 0953          } else if (sig.TopLevels.TryGetValue(name, out tdecl)) {
 0954            if (tdecl is ClassDecl && ((ClassDecl)tdecl).NonNullTypeDecl != null) {
 955              // cldecl is a possibly-null type (syntactically given with a question mark at the end)
 0956              var nn = ((ClassDecl)tdecl).NonNullTypeDecl;
 0957              Contract.Assert(nn != null);
 0958              reporter.Error(MessageSource.Resolver, export.Tok,
 0959                export.Opaque
 0960                  ? "Type '{1}' can only be revealed, not provided"
 0961                  : "Types '{0}' and '{1}' are exported together, which is accomplished by revealing the name '{0}'",
 0962                nn.Name, name);
 0963              continue;
 964            }
 965
 966            // Member of the enclosing module
 0967            decl = tdecl;
 0968          } else if (sig.StaticMembers.TryGetValue(name, out member)) {
 0969            decl = member;
 0970          } else if (sig.ExportSets.ContainsKey(name)) {
 0971            reporter.Error(MessageSource.Resolver, export.Tok,
 0972              "'{0}' is an export set and cannot be provided/revealed by another export set (did you intend to list it i
 0973              name);
 0974            continue;
 0975          } else {
 0976            reporter.Error(MessageSource.Resolver, export.Tok, "'{0}' must be a member of '{1}' to be exported", name,
 0977              m.Name);
 0978            continue;
 979          }
 980
 0981          if (!decl.CanBeExported()) {
 0982            reporter.Error(MessageSource.Resolver, export.Tok, "'{0}' is not a valid export of '{1}'", name, m.Name);
 0983            continue;
 984          }
 985
 0986          if (!export.Opaque && !decl.CanBeRevealed()) {
 0987            reporter.Error(MessageSource.Resolver, export.Tok,
 0988              "'{0}' cannot be revealed in an export. Use \"provides\" instead.", name);
 0989            continue;
 990          }
 991
 0992          export.Decl = decl;
 0993          if (decl is NonNullTypeDecl nntd) {
 0994            nntd.AddVisibilityScope(d.ThisScope, export.Opaque);
 0995            if (!export.Opaque) {
 0996              nntd.Class.AddVisibilityScope(d.ThisScope, export.Opaque);
 997              // add the anonymous constructor, if any
 0998              var anonymousConstructor = nntd.Class.Members.Find(mdecl => mdecl.Name == "_ctor");
 0999              if (anonymousConstructor != null) {
 01000                anonymousConstructor.AddVisibilityScope(d.ThisScope, false);
 01001              }
 01002            }
 01003          } else {
 01004            decl.AddVisibilityScope(d.ThisScope, export.Opaque);
 01005          }
 01006        }
 01007      }
 1008
 9181009      foreach (ModuleExportDecl decl in sortedExportDecls) {
 01010        if (decl.IsDefault) {
 01011          if (defaultExport == null) {
 01012            defaultExport = decl;
 01013          } else {
 01014            reporter.Error(MessageSource.Resolver, m.tok, "more than one default export set declared in module {0}",
 01015              m.Name);
 01016          }
 01017        }
 1018
 1019        // fill in export signature
 01020        ModuleSignature signature = decl.Signature;
 01021        if (signature != null) {
 01022          signature.ModuleDef = m;
 01023        }
 1024
 01025        foreach (var top in sig.TopLevels) {
 01026          if (!top.Value.CanBeExported() || !top.Value.IsVisibleInScope(signature.VisibilityScope)) {
 01027            continue;
 1028          }
 1029
 01030          if (!signature.TopLevels.ContainsKey(top.Key)) {
 01031            signature.TopLevels.Add(top.Key, top.Value);
 01032          }
 1033
 01034          if (top.Value is DatatypeDecl && top.Value.IsRevealedInScope(signature.VisibilityScope)) {
 01035            foreach (var ctor in ((DatatypeDecl)top.Value).Ctors) {
 01036              if (!signature.Ctors.ContainsKey(ctor.Name)) {
 01037                signature.Ctors.Add(ctor.Name, new Tuple<DatatypeCtor, bool>(ctor, false));
 01038              }
 01039            }
 01040          }
 01041        }
 1042
 01043        foreach (var mem in sig.StaticMembers.Where(t =>
 01044          t.Value.IsVisibleInScope(signature.VisibilityScope) && t.Value.CanBeExported())) {
 01045          if (!signature.StaticMembers.ContainsKey(mem.Key)) {
 01046            signature.StaticMembers.Add(mem.Key, (MemberDecl)mem.Value);
 01047          }
 01048        }
 01049      }
 1050
 1051      // set the default export set, if it exists
 3061052      if (defaultExport != null) {
 01053        literalDecl.DefaultExport = defaultExport.Signature;
 3061054      } else if (sortedExportDecls.Count > 0) {
 01055        literalDecl.DefaultExport = null;
 01056      }
 1057
 1058      // final pass to propagate visibility of exported imports
 3061059      var sigs = sortedExportDecls.Select(d => d.Signature).Concat1(sig);
 1060
 18361061      foreach (var s in sigs) {
 27391062        foreach (var decl in s.TopLevels) {
 6071063          if (decl.Value is ModuleDecl && !(decl.Value is ModuleExportDecl)) {
 01064            var modDecl = (ModuleDecl)decl.Value;
 01065            s.VisibilityScope.Augment(modDecl.AccessibleSignature().VisibilityScope);
 01066          }
 6071067        }
 3061068      }
 1069
 3061070      var exported = new HashSet<Tuple<Declaration, bool>>();
 1071
 1072      //some decls may not be set due to resolution errors
 9181073      foreach (var e in sortedExportDecls.SelectMany(e => e.Exports).Where(e => e.Decl != null)) {
 01074        var decl = e.Decl;
 01075        exported.Add(new Tuple<Declaration, bool>(decl, e.Opaque));
 01076        if (!e.Opaque && decl.CanBeRevealed()) {
 01077          exported.Add(new Tuple<Declaration, bool>(decl, true));
 01078          if (decl is NonNullTypeDecl nntd) {
 01079            exported.Add(new Tuple<Declaration, bool>(nntd.Class, true));
 01080          }
 01081        }
 1082
 01083        if (e.Opaque && (decl is DatatypeDecl || decl is TypeSynonymDecl)) {
 1084          // Datatypes and type synonyms are marked as _provided when they appear in any provided export.  If a
 1085          // declaration is never provided, then either it isn't visible outside the module at all or its whole
 1086          // definition is.  Datatype and type-synonym declarations undergo some inference from their definitions.
 1087          // Such inference should not be done for provided declarations, since different views of the module
 1088          // would then get different inferred properties.
 01089          decl.Attributes = new Attributes("_provided", new List<Expression>(), decl.Attributes);
 01090          reporter.Info(MessageSource.Resolver, decl.tok, "{:_provided}");
 01091        }
 01092      }
 1093
 3061094      Dictionary<RevealableTypeDecl, bool?> declScopes = new Dictionary<RevealableTypeDecl, bool?>();
 3061095      Dictionary<RevealableTypeDecl, bool?> modifies = new Dictionary<RevealableTypeDecl, bool?>();
 1096
 1097      //of all existing types, compute the minimum visibility of them for each exported declaration's
 1098      //body and signature
 9181099      foreach (var e in exported) {
 1100
 01101        declScopes.Clear();
 01102        modifies.Clear();
 1103
 01104        foreach (var typ in revealableTypes) {
 01105          declScopes.Add(typ, null);
 01106        }
 1107
 01108        foreach (var decl in sortedExportDecls) {
 01109          if (decl.Exports.Exists(ex => ex.Decl == e.Item1 && (e.Item2 || !ex.Opaque))) {
 1110            //if we are revealed, consider those exports where we are provided as well
 01111            var scope = decl.Signature.VisibilityScope;
 1112
 01113            foreach (var kv in declScopes) {
 01114              bool? isOpaque = kv.Value;
 01115              var typ = kv.Key;
 01116              if (!typ.AsTopLevelDecl.IsVisibleInScope(scope)) {
 01117                modifies[typ] = null;
 01118                continue;
 1119              }
 1120
 01121              if (isOpaque.HasValue && isOpaque.Value) {
 1122                //type is visible here, but known-opaque, so do nothing
 01123                continue;
 1124              }
 1125
 01126              modifies[typ] = !typ.AsTopLevelDecl.IsRevealedInScope(scope);
 01127            }
 1128
 01129            foreach (var kv in modifies) {
 01130              if (!kv.Value.HasValue) {
 01131                declScopes.Remove(kv.Key);
 01132              } else {
 01133                var exvis = declScopes[kv.Key];
 01134                if (exvis.HasValue) {
 01135                  declScopes[kv.Key] = exvis.Value || kv.Value.Value;
 01136                } else {
 01137                  declScopes[kv.Key] = kv.Value;
 01138                }
 01139              }
 01140            }
 1141
 01142            modifies.Clear();
 01143          }
 01144        }
 1145
 01146        VisibilityScope newscope = new VisibilityScope(e.Item1.Name);
 1147
 01148        foreach (var rt in declScopes) {
 01149          if (!rt.Value.HasValue) {
 01150            continue;
 1151          }
 1152
 01153          rt.Key.AsTopLevelDecl.AddVisibilityScope(newscope, rt.Value.Value);
 01154        }
 01155      }
 3061156    }
 1157
 1158    //check for export consistency by resolving internal modules
 1159    //this should be effect-free, as it only operates on clones
 2761160    private void CheckModuleExportConsistency(ModuleDefinition m) {
 2761161      var oldModuleInfo = moduleInfo;
 8281162      foreach (var exportDecl in m.TopLevelDecls.OfType<ModuleExportDecl>()) {
 1163
 01164        var prevErrors = reporter.Count(ErrorLevel.Error);
 1165
 01166        foreach (var export in exportDecl.Exports) {
 01167          if (export.Decl is MemberDecl member) {
 1168            // For classes and traits, the visibility test is performed on the corresponding non-null type
 01169            var enclosingType = member.EnclosingClass is ClassDecl cl && cl.NonNullTypeDecl != null
 01170              ? cl.NonNullTypeDecl
 01171              : member.EnclosingClass;
 01172            if (!enclosingType.IsVisibleInScope(exportDecl.Signature.VisibilityScope)) {
 01173              reporter.Error(MessageSource.Resolver, export.Tok,
 01174                "Cannot export type member '{0}' without providing its enclosing {1} '{2}'", member.Name,
 01175                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01176            } else if (member is Constructor &&
 01177                       !member.EnclosingClass.IsRevealedInScope(exportDecl.Signature.VisibilityScope)) {
 01178              reporter.Error(MessageSource.Resolver, export.Tok,
 01179                "Cannot export constructor '{0}' without revealing its enclosing {1} '{2}'", member.Name,
 01180                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01181            } else if (member is Field && !(member is ConstantField) &&
 01182                       !member.EnclosingClass.IsRevealedInScope(exportDecl.Signature.VisibilityScope)) {
 01183              reporter.Error(MessageSource.Resolver, export.Tok,
 01184                "Cannot export mutable field '{0}' without revealing its enclosing {1} '{2}'", member.Name,
 01185                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01186            }
 01187          }
 01188        }
 1189
 01190        var scope = exportDecl.Signature.VisibilityScope;
 01191        Cloner cloner = new ScopeCloner(scope);
 01192        var exportView = cloner.CloneModuleDefinition(m, m.NameNode);
 01193        if (Options.DafnyPrintExportedViews.Contains(exportDecl.FullName)) {
 01194          var wr = Options.OutputWriter;
 01195          wr.WriteLine("/* ===== export set {0}", exportDecl.FullName);
 01196          var pr = new Printer(wr, Options);
 01197          pr.PrintTopLevelDecls(exportView.TopLevelDecls, 0, null, null);
 01198          wr.WriteLine("*/");
 01199        }
 1200
 01201        if (reporter.Count(ErrorLevel.Error) != prevErrors) {
 01202          continue;
 1203        }
 1204
 01205        reporter = new ErrorReporterWrapper(reporter,
 01206          String.Format("Raised while checking export set {0}: ", exportDecl.Name));
 01207        var testSig = RegisterTopLevelDecls(exportView, true);
 1208        //testSig.Refines = refinementTransformer.RefinedSig;
 01209        ResolveModuleDefinition(exportView, testSig, true);
 01210        var wasError = reporter.Count(ErrorLevel.Error) > 0;
 01211        reporter = ((ErrorReporterWrapper)reporter).WrappedReporter;
 1212
 01213        if (wasError) {
 01214          reporter.Error(MessageSource.Resolver, exportDecl.tok, "This export set is not consistent: {0}", exportDecl.Na
 01215        }
 01216      }
 1217
 2761218      moduleInfo = oldModuleInfo;
 2761219    }
 1220
 1221    public class ModuleBindings {
 1222      private ModuleBindings parent;
 1223      private Dictionary<string, ModuleDecl> modules;
 1224      private Dictionary<string, ModuleBindings> bindings;
 1225
 12241226      public ModuleBindings(ModuleBindings p) {
 6121227        parent = p;
 6121228        modules = new Dictionary<string, ModuleDecl>();
 6121229        bindings = new Dictionary<string, ModuleBindings>();
 6121230      }
 1231
 3061232      public bool BindName(string name, ModuleDecl subModule, ModuleBindings b) {
 3061233        if (modules.ContainsKey(name)) {
 01234          return false;
 3061235        } else {
 3061236          modules.Add(name, subModule);
 3061237          bindings.Add(name, b);
 3061238          return true;
 1239        }
 3061240      }
 1241
 01242      public bool TryLookup(IToken name, out ModuleDecl m) {
 1243        Contract.Requires(name != null);
 01244        return TryLookupFilter(name, out m, l => true);
 01245      }
 1246
 01247      public bool TryLookupFilter(IToken name, out ModuleDecl m, Func<ModuleDecl, bool> filter) {
 1248        Contract.Requires(name != null);
 01249        if (modules.TryGetValue(name.val, out m) && filter(m)) {
 01250          return true;
 01251        } else if (parent != null) {
 01252          return parent.TryLookupFilter(name, out m, filter);
 01253        } else {
 01254          return false;
 1255        }
 01256      }
 1257
 1258      public IEnumerable<ModuleDecl> ModuleList {
 01259        get { return modules.Values; }
 1260      }
 1261
 01262      public ModuleBindings SubBindings(string name) {
 01263        ModuleBindings v = null;
 01264        bindings.TryGetValue(name, out v);
 01265        return v;
 01266      }
 1267    }
 1268
 3061269    private ModuleBindings BindModuleNames(ModuleDefinition moduleDecl, ModuleBindings parentBindings) {
 3061270      var bindings = new ModuleBindings(parentBindings);
 1271
 1272      // moduleDecl.PrefixNamedModules is a list of pairs like:
 1273      //     A.B.C  ,  module D { ... }
 1274      // We collect these according to the first component of the prefix, like so:
 1275      //     "A"   ->   (A.B.C  ,  module D { ... })
 3061276      var prefixNames = new Dictionary<string, List<Tuple<List<IToken>, LiteralModuleDecl>>>();
 9181277      foreach (var tup in moduleDecl.PrefixNamedModules) {
 01278        var id = tup.Item1[0].val;
 1279        List<Tuple<List<IToken>, LiteralModuleDecl>> prev;
 01280        if (!prefixNames.TryGetValue(id, out prev)) {
 01281          prev = new List<Tuple<List<IToken>, LiteralModuleDecl>>();
 01282        }
 1283
 01284        prev.Add(tup);
 01285        prefixNames[id] = prev;
 01286      }
 1287
 3061288      moduleDecl.PrefixNamedModules.Clear();
 1289
 1290      // First, register all literal modules, and transferring their prefix-named modules downwards
 27391291      foreach (var tld in moduleDecl.TopLevelDecls) {
 6071292        if (tld is LiteralModuleDecl) {
 01293          var subdecl = (LiteralModuleDecl)tld;
 1294          // Transfer prefix-named modules downwards into the sub-module
 1295          List<Tuple<List<IToken>, LiteralModuleDecl>> prefixModules;
 01296          if (prefixNames.TryGetValue(subdecl.Name, out prefixModules)) {
 01297            prefixNames.Remove(subdecl.Name);
 01298            prefixModules = prefixModules.ConvertAll(ShortenPrefix);
 01299          } else {
 01300            prefixModules = null;
 01301          }
 1302
 01303          BindModuleName_LiteralModuleDecl(subdecl, prefixModules, bindings);
 01304        }
 6071305      }
 1306
 1307      // Next, add new modules for any remaining entries in "prefixNames".
 9181308      foreach (var entry in prefixNames) {
 01309        var name = entry.Key;
 01310        var prefixNamedModules = entry.Value;
 01311        var tok = prefixNamedModules.First().Item1[0];
 01312        var modDef = new ModuleDefinition(tok.ToRange(), new Name(tok.ToRange(), name), new List<IToken>(), false, false
 01313          true, true);
 1314        // Every module is expected to have a default class, so we create and add one now
 01315        var defaultClass = new DefaultClassDecl(modDef, new List<MemberDecl>());
 01316        modDef.TopLevelDecls.Add(defaultClass);
 1317        // Add the new module to the top-level declarations of its parent and then bind its names as usual
 01318        var subdecl = new LiteralModuleDecl(modDef, moduleDecl);
 01319        moduleDecl.TopLevelDecls.Add(subdecl);
 01320        BindModuleName_LiteralModuleDecl(subdecl, prefixNamedModules.ConvertAll(ShortenPrefix), bindings);
 01321      }
 1322
 1323      // Finally, go through import declarations (that is, AbstractModuleDecl's and AliasModuleDecl's).
 27391324      foreach (var tld in moduleDecl.TopLevelDecls) {
 6071325        if (tld is AbstractModuleDecl || tld is AliasModuleDecl) {
 01326          var subdecl = (ModuleDecl)tld;
 01327          if (bindings.BindName(subdecl.Name, subdecl, null)) {
 1328            // the add was successful
 01329          } else {
 1330            // there's already something with this name
 1331            ModuleDecl prevDecl;
 01332            var yes = bindings.TryLookup(subdecl.tok, out prevDecl);
 01333            Contract.Assert(yes);
 01334            if (prevDecl is AbstractModuleDecl || prevDecl is AliasModuleDecl) {
 01335              reporter.Error(MessageSource.Resolver, subdecl.tok, "Duplicate name of import: {0}", subdecl.Name);
 01336            } else if (tld is AliasModuleDecl importDecl && importDecl.Opened && importDecl.TargetQId.Path.Count == 1 &&
 01337                       importDecl.Name == importDecl.TargetQId.rootName()) {
 01338              importDecl.ShadowsLiteralModule = true;
 01339            } else {
 01340              reporter.Error(MessageSource.Resolver, subdecl.tok,
 01341                "Import declaration uses same name as a module in the same scope: {0}", subdecl.Name);
 01342            }
 01343          }
 01344        }
 6071345      }
 1346
 3061347      return bindings;
 3061348    }
 1349
 01350    private Tuple<List<IToken>, LiteralModuleDecl> ShortenPrefix(Tuple<List<IToken>, LiteralModuleDecl> tup) {
 1351      Contract.Requires(tup.Item1.Count != 0);
 01352      var rest = tup.Item1.GetRange(1, tup.Item1.Count - 1);
 01353      return new Tuple<List<IToken>, LiteralModuleDecl>(rest, tup.Item2);
 01354    }
 1355
 1356    private void BindModuleName_LiteralModuleDecl(LiteralModuleDecl litmod,
 01357      List<Tuple<List<IToken>, LiteralModuleDecl>> /*?*/ prefixModules, ModuleBindings parentBindings) {
 1358      Contract.Requires(litmod != null);
 1359      Contract.Requires(parentBindings != null);
 1360
 1361      // Transfer prefix-named modules downwards into the sub-module
 01362      if (prefixModules != null) {
 01363        foreach (var tup in prefixModules) {
 01364          if (tup.Item1.Count == 0) {
 01365            tup.Item2.ModuleDef.EnclosingModule =
 01366              litmod.ModuleDef; // change the parent, now that we have found the right parent module for the prefix-name
 01367            var sm = new LiteralModuleDecl(tup.Item2.ModuleDef,
 01368              litmod.ModuleDef); // this will create a ModuleDecl with the right parent
 01369            litmod.ModuleDef.TopLevelDecls.Add(sm);
 01370          } else {
 01371            litmod.ModuleDef.PrefixNamedModules.Add(tup);
 01372          }
 01373        }
 01374      }
 1375
 01376      var bindings = BindModuleNames(litmod.ModuleDef, parentBindings);
 01377      if (!parentBindings.BindName(litmod.Name, litmod, bindings)) {
 01378        reporter.Error(MessageSource.Resolver, litmod.tok, "Duplicate module name: {0}", litmod.Name);
 01379      }
 01380    }
 1381
 1382    private bool ResolveQualifiedModuleIdRootRefines(ModuleDefinition context, ModuleBindings bindings, ModuleQualifiedI
 01383      out ModuleDecl result) {
 01384      Contract.Assert(qid != null);
 01385      IToken root = qid.Path[0].StartToken;
 01386      result = null;
 01387      bool res = bindings.TryLookupFilter(root, out result, m => m.EnclosingModuleDefinition != context);
 01388      qid.Root = result;
 01389      return res;
 01390    }
 1391
 1392    // Find a matching module for the root of the QualifiedId, ignoring
 1393    // (a) the module (context) itself and (b) any local imports
 1394    // The latter is so that if one writes 'import A`E  import F = A`F' the second A does not
 1395    // resolve to the alias produced by the first import
 1396    private bool ResolveQualifiedModuleIdRootImport(AliasModuleDecl context, ModuleBindings bindings, ModuleQualifiedId 
 01397      out ModuleDecl result) {
 01398      Contract.Assert(qid != null);
 01399      IToken root = qid.Path[0].StartToken;
 01400      result = null;
 01401      bool res = bindings.TryLookupFilter(root, out result,
 01402        m => context != m && ((context.EnclosingModuleDefinition == m.EnclosingModuleDefinition && context.Exports.Count
 01403      qid.Root = result;
 01404      return res;
 01405    }
 1406
 1407    private bool ResolveQualifiedModuleIdRootAbstract(AbstractModuleDecl context, ModuleBindings bindings, ModuleQualifi
 01408      out ModuleDecl result) {
 01409      Contract.Assert(qid != null);
 01410      IToken root = qid.Path[0].StartToken;
 01411      result = null;
 01412      bool res = bindings.TryLookupFilter(root, out result,
 01413        m => context != m && ((context.EnclosingModuleDefinition == m.EnclosingModuleDefinition && context.Exports.Count
 01414      qid.Root = result;
 01415      return res;
 01416    }
 1417
 1418    private void ProcessDependenciesDefinition(ModuleDecl decl, ModuleDefinition m, ModuleBindings bindings,
 3061419      Graph<ModuleDecl> dependencies) {
 3061420      Contract.Assert(decl is LiteralModuleDecl);
 3061421      if (m.RefinementQId != null) {
 1422        ModuleDecl other;
 01423        bool res = ResolveQualifiedModuleIdRootRefines(((LiteralModuleDecl)decl).ModuleDef, bindings, m.RefinementQId, o
 01424        if (!res) {
 01425          reporter.Error(MessageSource.Resolver, m.RefinementQId.rootToken(),
 01426            $"module {m.RefinementQId.ToString()} named as refinement base does not exist");
 01427        } else if (other is LiteralModuleDecl && ((LiteralModuleDecl)other).ModuleDef == m) {
 01428          reporter.Error(MessageSource.Resolver, m.RefinementQId.rootToken(), "module cannot refine itself: {0}",
 01429            m.RefinementQId.ToString());
 01430        } else {
 01431          Contract.Assert(other != null); // follows from postcondition of TryGetValue
 01432          dependencies.AddEdge(decl, other);
 01433        }
 01434      }
 1435
 27391436      foreach (var toplevel in m.TopLevelDecls) {
 6071437        if (toplevel is ModuleDecl) {
 01438          var d = (ModuleDecl)toplevel;
 01439          dependencies.AddEdge(decl, d);
 01440          var subbindings = bindings.SubBindings(d.Name);
 01441          ProcessDependencies(d, subbindings ?? bindings, dependencies);
 01442          if (!m.IsAbstract && d is AbstractModuleDecl && ((AbstractModuleDecl)d).QId.Root != null) {
 01443            reporter.Error(MessageSource.Resolver, d.tok,
 01444              "The abstract import named {0} (using :) may only be used in an abstract module declaration",
 01445              d.Name);
 01446          }
 01447        }
 6071448      }
 3061449    }
 1450
 3061451    private void ProcessDependencies(ModuleDecl moduleDecl, ModuleBindings bindings, Graph<ModuleDecl> dependencies) {
 3061452      dependencies.AddVertex(moduleDecl);
 6121453      if (moduleDecl is LiteralModuleDecl) {
 3061454        ProcessDependenciesDefinition(moduleDecl, ((LiteralModuleDecl)moduleDecl).ModuleDef, bindings, dependencies);
 3061455      } else if (moduleDecl is AliasModuleDecl) {
 01456        var alias = moduleDecl as AliasModuleDecl;
 1457        ModuleDecl root;
 1458        // TryLookupFilter works outward, looking for a match to the filter for
 1459        // each enclosing module.
 01460        if (!ResolveQualifiedModuleIdRootImport(alias, bindings, alias.TargetQId, out root)) {
 1461          //        if (!bindings.TryLookupFilter(alias.TargetQId.rootToken(), out root, m => alias != m)
 01462          reporter.Error(MessageSource.Resolver, alias.tok, ModuleNotFoundErrorMessage(0, alias.TargetQId.Path));
 01463        } else {
 01464          dependencies.AddEdge(moduleDecl, root);
 01465        }
 01466      } else if (moduleDecl is AbstractModuleDecl) {
 01467        var abs = moduleDecl as AbstractModuleDecl;
 1468        ModuleDecl root;
 01469        if (!ResolveQualifiedModuleIdRootAbstract(abs, bindings, abs.QId, out root)) {
 1470          //if (!bindings.TryLookupFilter(abs.QId.rootToken(), out root,
 1471          //  m => abs != m && (((abs.EnclosingModuleDefinition == m.EnclosingModuleDefinition) && (abs.Exports.Count ==
 01472          reporter.Error(MessageSource.Resolver, abs.tok, ModuleNotFoundErrorMessage(0, abs.QId.Path));
 01473        } else {
 01474          dependencies.AddEdge(moduleDecl, root);
 01475        }
 01476      }
 3061477    }
 1478
 01479    private static string ModuleNotFoundErrorMessage(int i, List<Name> path, string tail = "") {
 1480      Contract.Requires(path != null);
 1481      Contract.Requires(0 <= i && i < path.Count);
 01482      return "module " + path[i].Value + " does not exist" +
 01483             (1 < path.Count
 01484               ? " (position " + i.ToString() + " in path " + Util.Comma(".", path, x => x.Value) + ")" + tail
 01485               : "");
 01486    }
 1487
 1488    private static bool EquivIfPresent<T1, T2>(Dictionary<T1, T2> dic, T1 key, T2 val)
 62431489      where T2 : class {
 1490      T2 val2;
 62431491      if (dic.TryGetValue(key, out val2)) {
 01492        return val.Equals(val2);
 1493      }
 1494
 62431495      return true;
 62431496    }
 1497
 5821498    public static ModuleSignature MergeSignature(ModuleSignature m, ModuleSignature system) {
 1499      Contract.Requires(m != null);
 1500      Contract.Requires(system != null);
 5821501      var info = new ModuleSignature();
 1502      // add the system-declared information, among which we know there are no duplicates
 390931503      foreach (var kv in system.TopLevels) {
 124491504        info.TopLevels.Add(kv.Key, kv.Value);
 124491505      }
 1506
 59191507      foreach (var kv in system.Ctors) {
 13911508        info.Ctors.Add(kv.Key, kv.Value);
 13911509      }
 1510
 17461511      foreach (var kv in system.StaticMembers) {
 01512        info.StaticMembers.Add(kv.Key, kv.Value);
 01513      }
 1514
 1515      // add for the module itself
 50731516      foreach (var kv in m.TopLevels) {
 11091517        if (info.TopLevels.TryGetValue(kv.Key, out var infoValue)) {
 01518          if (infoValue != kv.Value) {
 1519            // This only happens if one signature contains the name C as a class C (because it
 1520            // provides C) and the other signature contains the name C as a non-null type decl
 1521            // (because it reveals C and C?). The merge output will contain the non-null type decl
 1522            // for the key (and we expect the mapping "C? -> class C" to be placed in the
 1523            // merge output as well, by the end of this loop).
 01524            if (infoValue is ClassDecl) {
 01525              var cd = (ClassDecl)infoValue;
 01526              Contract.Assert(cd.NonNullTypeDecl == kv.Value);
 01527              info.TopLevels[kv.Key] = kv.Value;
 01528            } else if (kv.Value is ClassDecl) {
 01529              var cd = (ClassDecl)kv.Value;
 01530              Contract.Assert(cd.NonNullTypeDecl == infoValue);
 1531              // info.TopLevel[kv.Key] already has the right value
 01532            } else {
 01533              Contract.Assert(false); // unexpected
 01534            }
 1535
 01536            continue;
 1537          }
 01538        }
 1539
 11091540        info.TopLevels[kv.Key] = kv.Value;
 11091541      }
 1542
 47821543      foreach (var kv in m.Ctors) {
 10121544        Contract.Assert(EquivIfPresent(info.Ctors, kv.Key, kv.Value));
 10121545        info.Ctors[kv.Key] = kv.Value;
 10121546      }
 1547
 174391548      foreach (var kv in m.StaticMembers) {
 52311549        Contract.Assert(EquivIfPresent(info.StaticMembers, kv.Key, kv.Value));
 52311550        info.StaticMembers[kv.Key] = kv.Value;
 52311551      }
 1552
 5821553      info.IsAbstract = m.IsAbstract;
 5821554      info.VisibilityScope = new VisibilityScope();
 5821555      info.VisibilityScope.Augment(m.VisibilityScope);
 5821556      info.VisibilityScope.Augment(system.VisibilityScope);
 5821557      return info;
 5821558    }
 1559
 1560    public static void ResolveOpenedImports(ModuleSignature sig, ModuleDefinition moduleDef, bool useCompileSignatures,
 5821561      Resolver resolver) {
 5821562      var declarations = sig.TopLevels.Values.ToList<TopLevelDecl>();
 5821563      var importedSigs = new HashSet<ModuleSignature>() { sig };
 1564
 5821565      var topLevelDeclReplacements = new List<TopLevelDecl>();
 424201566      foreach (var top in declarations) {
 135581567        if (top is ModuleDecl md && md.Opened) {
 01568          ResolveOpenedImportsWorker(sig, moduleDef, (ModuleDecl)top, importedSigs, useCompileSignatures, out var topLev
 01569          if (topLevelDeclReplacement != null) {
 01570            topLevelDeclReplacements.Add(topLevelDeclReplacement);
 01571          }
 01572        }
 135581573      }
 17461574      foreach (var topLevelDeclReplacement in topLevelDeclReplacements) {
 01575        if (sig.TopLevels.GetValueOrDefault(topLevelDeclReplacement.Name) is ModuleDecl moduleDecl) {
 01576          sig.ShadowedImportedModules[topLevelDeclReplacement.Name] = moduleDecl;
 01577        }
 01578        sig.TopLevels[topLevelDeclReplacement.Name] = topLevelDeclReplacement;
 01579      }
 1580
 11641581      if (resolver != null) {
 1582        //needed because ResolveOpenedImports is used statically for a refinement check
 5821583        if (sig.TopLevels["_default"] is AmbiguousTopLevelDecl) {
 01584          Contract.Assert(sig.TopLevels["_default"].WhatKind == "class");
 01585          var cl = new DefaultClassDecl(moduleDef, sig.StaticMembers.Values.ToList());
 01586          sig.TopLevels["_default"] = cl;
 01587          resolver.classMembers[cl] = cl.Members.ToDictionary(m => m.Name);
 01588        }
 5821589      }
 5821590    }
 1591
 01592    static TopLevelDecl ResolveAlias(TopLevelDecl dd) {
 01593      while (dd is AliasModuleDecl amd) {
 01594        dd = amd.TargetQId.Root;
 01595      }
 01596      return dd;
 01597    }
 1598
 1599    /// <summary>
 1600    /// Further populate "sig" with the accessible symbols from "im".
 1601    ///
 1602    /// Symbols declared locally in "moduleDef" take priority over any opened-import symbols, with one
 1603    /// exception:  for an "import opened M" where "M" contains a top-level symbol "M", unambiguously map the
 1604    /// name "M" to that top-level symbol in "sig". To achieve the "unambiguously" part, return the desired mapping
 1605    /// to the caller, and let the caller remap the symbol after all opened imports have been processed.
 1606    /// </summary>
 1607    static void ResolveOpenedImportsWorker(ModuleSignature sig, ModuleDefinition moduleDef, ModuleDecl im, HashSet<Modul
 01608      bool useCompileSignatures, out TopLevelDecl topLevelDeclReplacement) {
 1609
 01610      topLevelDeclReplacement = null;
 01611      var s = GetSignatureExt(im.AccessibleSignature(useCompileSignatures), useCompileSignatures);
 1612
 01613      if (importedSigs.Contains(s)) {
 01614        return; // we've already got these declarations
 1615      }
 1616
 01617      importedSigs.Add(s);
 1618
 1619      // top-level declarations:
 01620      foreach (var kv in s.TopLevels) {
 01621        if (!kv.Value.CanBeExported()) {
 01622          continue;
 1623        }
 1624
 01625        if (!sig.TopLevels.TryGetValue(kv.Key, out var d)) {
 01626          sig.TopLevels.Add(kv.Key, kv.Value);
 01627        } else if (d.EnclosingModuleDefinition == moduleDef) {
 01628          if (kv.Value.EnclosingModuleDefinition.DafnyName != kv.Key) {
 1629            // declarations in the importing module take priority over opened-import declarations
 01630          } else {
 1631            // As an exception to the rule, for an "import opened M" that contains a top-level symbol "M", unambiguously
 1632            // name "M" to that top-level symbol in "sig". To achieve the "unambiguously" part, return the desired mappi
 1633            // the caller, and let the caller remap the symbol after all opened imports have been processed.
 01634            topLevelDeclReplacement = kv.Value;
 01635          }
 01636        } else {
 01637          bool unambiguous = false;
 1638          // keep just one if they normalize to the same entity
 01639          if (d == kv.Value) {
 01640            unambiguous = true;
 01641          } else if (d is ModuleDecl || kv.Value is ModuleDecl) {
 01642            var dd = ResolveAlias(d);
 01643            var dk = ResolveAlias(kv.Value);
 01644            unambiguous = dd == dk;
 01645          } else {
 1646            // It's okay if "d" and "kv.Value" denote the same type. This can happen, for example,
 1647            // if both are type synonyms for "int".
 01648            var scope = Type.GetScope();
 01649            if (d.IsVisibleInScope(scope) && kv.Value.IsVisibleInScope(scope)) {
 01650              var dType = UserDefinedType.FromTopLevelDecl(d.tok, d);
 01651              var vType = UserDefinedType.FromTopLevelDecl(kv.Value.tok, kv.Value);
 01652              unambiguous = dType.Equals(vType, true);
 01653            }
 01654          }
 01655          if (!unambiguous) {
 01656            sig.TopLevels[kv.Key] = AmbiguousTopLevelDecl.Create(moduleDef, d, kv.Value);
 01657          }
 01658        }
 01659      }
 1660
 1661      // constructors:
 01662      foreach (var kv in s.Ctors) {
 01663        if (sig.Ctors.TryGetValue(kv.Key, out var pair)) {
 1664          // The same ctor can be imported from two different imports (e.g "diamond" imports), in which case,
 1665          // they are not duplicates.
 01666          if (!Object.ReferenceEquals(kv.Value.Item1, pair.Item1)) {
 1667            // mark it as a duplicate
 01668            sig.Ctors[kv.Key] = new Tuple<DatatypeCtor, bool>(pair.Item1, true);
 01669          }
 01670        } else {
 1671          // add new
 01672          sig.Ctors.Add(kv.Key, kv.Value);
 01673        }
 01674      }
 1675
 1676      // static members:
 01677      foreach (var kv in s.StaticMembers) {
 01678        if (!kv.Value.CanBeExported()) {
 01679          continue;
 1680        }
 1681
 01682        if (sig.StaticMembers.TryGetValue(kv.Key, out var md)) {
 01683          sig.StaticMembers[kv.Key] = AmbiguousMemberDecl.Create(moduleDef, md, kv.Value);
 01684        } else {
 1685          // add new
 01686          sig.StaticMembers.Add(kv.Key, kv.Value);
 01687        }
 01688      }
 01689    }
 1690
 8881691    ModuleSignature RegisterTopLevelDecls(ModuleDefinition moduleDef, bool useImports) {
 1692      Contract.Requires(moduleDef != null);
 8881693      var sig = new ModuleSignature();
 8881694      sig.ModuleDef = moduleDef;
 8881695      sig.IsAbstract = moduleDef.IsAbstract;
 8881696      sig.VisibilityScope = new VisibilityScope();
 8881697      sig.VisibilityScope.Augment(moduleDef.VisibilityScope);
 1698
 8881699      List<TopLevelDecl> declarations = moduleDef.TopLevelDecls;
 1700
 1701      // This is solely used to detect duplicates amongst the various e
 8881702      Dictionary<string, TopLevelDecl> toplevels = new Dictionary<string, TopLevelDecl>();
 1703      // Now add the things present
 8881704      var anonymousImportCount = 0;
 238111705      foreach (TopLevelDecl d in declarations) {
 70491706        Contract.Assert(d != null);
 1707
 119561708        if (d is RevealableTypeDecl) {
 49071709          revealableTypes.Add((RevealableTypeDecl)d);
 49071710        }
 1711
 1712        // register the class/datatype/module name
 70491713        {
 70491714          TopLevelDecl registerThisDecl = null;
 70491715          string registerUnderThisName = null;
 70491716          if (d is ModuleExportDecl export) {
 01717            if (sig.ExportSets.ContainsKey(d.Name)) {
 01718              reporter.Error(MessageSource.Resolver, d, "duplicate name of export set: {0}", d.Name);
 01719            } else {
 01720              sig.ExportSets[d.Name] = export;
 01721            }
 70491722          } else if (d is AliasModuleDecl importDecl && importDecl.ShadowsLiteralModule) {
 1723            // add under an anonymous name
 01724            registerThisDecl = d;
 01725            registerUnderThisName = string.Format("{0}#{1}", d.Name, anonymousImportCount);
 01726            anonymousImportCount++;
 70491727          } else if (toplevels.ContainsKey(d.Name)) {
 01728            reporter.Error(MessageSource.Resolver, d, "duplicate name of top-level declaration: {0}", d.Name);
 76611729          } else if (d is ClassDecl cl && cl.NonNullTypeDecl != null) {
 6121730            registerThisDecl = cl.NonNullTypeDecl;
 6121731            registerUnderThisName = d.Name;
 70491732          } else {
 64371733            registerThisDecl = d;
 64371734            registerUnderThisName = d.Name;
 64371735          }
 1736
 140981737          if (registerThisDecl != null) {
 70491738            toplevels[registerUnderThisName] = registerThisDecl;
 70491739            sig.TopLevels[registerUnderThisName] = registerThisDecl;
 70491740          }
 70491741        }
 70491742        if (d is ModuleDecl) {
 1743          // nothing to do
 88851744        } else if (d is TypeSynonymDecl) {
 1745          // nothing more to register
 70491746        } else if (d is NewtypeDecl || d is AbstractTypeDecl) {
 01747          var cl = (TopLevelDeclWithMembers)d;
 1748          // register the names of the type members
 01749          var members = new Dictionary<string, MemberDecl>();
 01750          classMembers.Add(cl, members);
 01751          RegisterMembers(moduleDef, cl, members);
 52131752        } else if (d is IteratorDecl) {
 01753          var iter = (IteratorDecl)d;
 1754
 01755          iter.Resolve(this);
 70191756        } else if (d is ClassDecl) {
 18061757          var cl = (ClassDecl)d;
 18061758          var preMemberErrs = reporter.Count(ErrorLevel.Error);
 1759
 1760          // register the names of the class members
 18061761          var members = new Dictionary<string, MemberDecl>();
 18061762          classMembers.Add(cl, members);
 18061763          RegisterMembers(moduleDef, cl, members);
 1764
 18061765          Contract.Assert(preMemberErrs != reporter.Count(ErrorLevel.Error) ||
 18061766                          !cl.Members.Except(members.Values).Any());
 1767
 23881768          if (cl.IsDefaultClass) {
 174391769            foreach (MemberDecl m in members.Values) {
 52311770              Contract.Assert(!m.HasStaticKeyword || m is ConstantField); // note, the IsStatic value isn't available ye
 104621771              if (m is Function || m is Method || m is ConstantField) {
 52311772                sig.StaticMembers[m.Name] = m;
 52311773              }
 1774
 52311775              if (toplevels.ContainsKey(m.Name)) {
 01776                reporter.Error(MessageSource.Resolver, m.tok,
 01777                  $"duplicate declaration for name {m.Name}");
 01778              }
 52311779            }
 5821780          }
 1781
 64781782        } else if (d is DatatypeDecl) {
 12651783          var dt = (DatatypeDecl)d;
 1784
 1785          // register the names of the constructors
 12651786          dt.ConstructorsByName = new();
 1787          // ... and of the other members
 12651788          var members = new Dictionary<string, MemberDecl>();
 12651789          classMembers.Add(dt, members);
 1790
 90451791          foreach (DatatypeCtor ctor in dt.Ctors) {
 17501792            if (ctor.Name.EndsWith("?")) {
 01793              reporter.Error(MessageSource.Resolver, ctor,
 01794                "a datatype constructor name is not allowed to end with '?'");
 17501795            } else if (dt.ConstructorsByName.ContainsKey(ctor.Name)) {
 01796              reporter.Error(MessageSource.Resolver, ctor, "Duplicate datatype constructor name: {0}", ctor.Name);
 17501797            } else {
 17501798              dt.ConstructorsByName.Add(ctor.Name, ctor);
 17501799              ctor.InheritVisibility(dt);
 1800
 1801              // create and add the query "method" (field, really)
 17501802              var queryName = ctor.NameNode.Append("?");
 17501803              var query = new DatatypeDiscriminator(ctor.RangeToken, queryName, SpecialField.ID.UseIdParam, "is_" + ctor
 17501804                ctor.IsGhost, Type.Bool, null);
 17501805              query.InheritVisibility(dt);
 17501806              query.EnclosingClass = dt; // resolve here
 17501807              members.Add(queryName.Value, query);
 17501808              ctor.QueryField = query;
 1809
 1810              // also register the constructor name globally
 1811              Tuple<DatatypeCtor, bool> pair;
 17501812              if (sig.Ctors.TryGetValue(ctor.Name, out pair)) {
 1813                // mark it as a duplicate
 01814                sig.Ctors[ctor.Name] = new Tuple<DatatypeCtor, bool>(pair.Item1, true);
 17501815              } else {
 1816                // add new
 17501817                sig.Ctors.Add(ctor.Name, new Tuple<DatatypeCtor, bool>(ctor, false));
 17501818              }
 17501819            }
 17501820          }
 1821
 1822          // add deconstructors now (that is, after the query methods have been added)
 90451823          foreach (DatatypeCtor ctor in dt.Ctors) {
 17501824            var formalsUsedInThisCtor = new HashSet<string>();
 17501825            var duplicates = new HashSet<Formal>();
 106801826            foreach (var formal in ctor.Formals) {
 18101827              MemberDecl previousMember = null;
 18101828              var localDuplicate = false;
 36201829              if (formal.HasName) {
 18101830                if (members.TryGetValue(formal.Name, out previousMember)) {
 01831                  localDuplicate = formalsUsedInThisCtor.Contains(formal.Name);
 01832                  if (localDuplicate) {
 01833                    reporter.Error(MessageSource.Resolver, ctor,
 01834                      "Duplicate use of deconstructor name in the same constructor: {0}", formal.Name);
 01835                    duplicates.Add(formal);
 01836                  } else if (previousMember is DatatypeDestructor) {
 1837                    // this is okay, if the destructor has the appropriate type; this will be checked later, after type 
 01838                  } else {
 01839                    reporter.Error(MessageSource.Resolver, ctor,
 01840                      "Name of deconstructor is used by another member of the datatype: {0}", formal.Name);
 01841                  }
 01842                }
 1843
 18101844                formalsUsedInThisCtor.Add(formal.Name);
 18101845              }
 1846
 1847              DatatypeDestructor dtor;
 18101848              if (!localDuplicate && previousMember is DatatypeDestructor) {
 1849                // a destructor with this name already existed in (a different constructor in) the datatype
 01850                dtor = (DatatypeDestructor)previousMember;
 01851                dtor.AddAnotherEnclosingCtor(ctor, formal);
 18101852              } else {
 1853                // either the destructor has no explicit name, or this constructor declared another destructor with this
 18101854                dtor = new DatatypeDestructor(formal.RangeToken, ctor, formal, new Name(formal.RangeToken, formal.Name),
 18101855                  formal.IsGhost, formal.Type, null);
 18101856                dtor.InheritVisibility(dt);
 18101857                dtor.EnclosingClass = dt; // resolve here
 36201858                if (formal.HasName && !localDuplicate && previousMember == null) {
 1859                  // the destructor has an explict name and there was no member at all with this name before
 18101860                  members.Add(formal.Name, dtor);
 18101861                }
 18101862              }
 1863
 18101864              ctor.Destructors.Add(dtor);
 18101865            }
 1866
 52501867            foreach (var duplicate in duplicates) {
 01868              ctor.Formals.Remove(duplicate);
 01869            }
 17501870          }
 1871
 1872          // finally, add any additional user-defined members
 12651873          RegisterMembers(moduleDef, dt, members);
 34071874        } else {
 21421875          Contract.Assert(d is ValuetypeDecl);
 21421876        }
 70491877      }
 1878
 1879      // Now, for each class, register its possibly-null type
 238111880      foreach (TopLevelDecl d in declarations) {
 76611881        if ((d as ClassDecl)?.NonNullTypeDecl != null) {
 6121882          var name = d.Name + "?";
 1883          TopLevelDecl prev;
 6121884          if (toplevels.TryGetValue(name, out prev)) {
 01885            reporter.Error(MessageSource.Resolver, d,
 01886              "a module that already contains a top-level declaration '{0}' is not allowed to declare a {1} '{2}'",
 01887              name, d.WhatKind, d.Name);
 6121888          } else {
 6121889            toplevels[name] = d;
 6121890            sig.TopLevels[name] = d;
 6121891          }
 6121892        }
 70491893      }
 1894
 8881895      return sig;
 8881896    }
 1897
 1898    void RegisterMembers(ModuleDefinition moduleDef, TopLevelDeclWithMembers cl,
 30711899      Dictionary<string, MemberDecl> members) {
 1900      Contract.Requires(moduleDef != null);
 1901      Contract.Requires(cl != null);
 1902      Contract.Requires(members != null);
 1903
 294961904      foreach (MemberDecl m in cl.Members) {
 135221905        if (!members.ContainsKey(m.Name)) {
 67611906          members.Add(m.Name, m);
 67611907          if (m is Constructor) {
 01908            Contract.Assert(cl is ClassDecl); // the parser ensures this condition
 01909            if (cl is TraitDecl) {
 01910              reporter.Error(MessageSource.Resolver, m.tok, "a trait is not allowed to declare a constructor");
 01911            } else {
 01912              ((ClassDecl)cl).HasConstructor = true;
 01913            }
 67611914          } else if (m is ExtremePredicate || m is ExtremeLemma) {
 01915            var extraName = m.NameNode.Append("#");
 1916            MemberDecl extraMember;
 01917            var cloner = new Cloner();
 01918            var formals = new List<Formal>();
 1919            Type typeOfK;
 01920            if ((m is ExtremePredicate && ((ExtremePredicate)m).KNat) ||
 01921                (m is ExtremeLemma && ((ExtremeLemma)m).KNat)) {
 01922              typeOfK = new UserDefinedType(m.tok, "nat", (List<Type>)null);
 01923            } else {
 01924              typeOfK = new BigOrdinalType();
 01925            }
 1926
 01927            var k = new ImplicitFormal(m.tok, "_k", typeOfK, true, false);
 01928            reporter.Info(MessageSource.Resolver, m.tok, string.Format("_k: {0}", k.Type));
 01929            formals.Add(k);
 01930            if (m is ExtremePredicate extremePredicate) {
 01931              formals.AddRange(extremePredicate.Formals.ConvertAll(f => cloner.CloneFormal(f, false)));
 1932
 01933              List<TypeParameter> tyvars = extremePredicate.TypeArgs.ConvertAll(cloner.CloneTypeParam);
 1934
 1935              // create prefix predicate
 01936              extremePredicate.PrefixPredicate = new PrefixPredicate(extremePredicate.RangeToken, extraName, extremePred
 01937                tyvars, k, formals,
 01938                extremePredicate.Req.ConvertAll(cloner.CloneAttributedExpr),
 01939                extremePredicate.Reads.ConvertAll(cloner.CloneFrameExpr),
 01940                extremePredicate.Ens.ConvertAll(cloner.CloneAttributedExpr),
 01941                new Specification<Expression>(new List<Expression>() { new IdentifierExpr(extremePredicate.tok, k.Name) 
 01942                cloner.CloneExpr(extremePredicate.Body),
 01943                null,
 01944                extremePredicate);
 01945              extraMember = extremePredicate.PrefixPredicate;
 01946            } else {
 01947              var extremeLemma = (ExtremeLemma)m;
 1948              // _k has already been added to 'formals', so append the original formals
 01949              formals.AddRange(extremeLemma.Ins.ConvertAll(f => cloner.CloneFormal(f, false)));
 1950              // prepend _k to the given decreases clause
 01951              var decr = new List<Expression>();
 01952              decr.Add(new IdentifierExpr(extremeLemma.tok, k.Name));
 01953              decr.AddRange(extremeLemma.Decreases.Expressions.ConvertAll(cloner.CloneExpr));
 1954              // Create prefix lemma.  Note that the body is not cloned, but simply shared.
 1955              // For a greatest lemma, the postconditions are filled in after the greatest lemma's postconditions have b
 1956              // For a least lemma, the preconditions are filled in after the least lemma's preconditions have been reso
 01957              var req = extremeLemma is GreatestLemma
 01958                ? extremeLemma.Req.ConvertAll(cloner.CloneAttributedExpr)
 01959                : new List<AttributedExpression>();
 01960              var ens = extremeLemma is GreatestLemma
 01961                ? new List<AttributedExpression>()
 01962                : extremeLemma.Ens.ConvertAll(cloner.CloneAttributedExpr);
 01963              extremeLemma.PrefixLemma = new PrefixLemma(extremeLemma.RangeToken, extraName, extremeLemma.HasStaticKeywo
 01964                extremeLemma.TypeArgs.ConvertAll(cloner.CloneTypeParam), k, formals, extremeLemma.Outs.ConvertAll(f => c
 01965                req, cloner.CloneSpecFrameExpr(extremeLemma.Mod), ens,
 01966                new Specification<Expression>(decr, null),
 01967                null, // Note, the body for the prefix method will be created once the call graph has been computed and 
 01968                cloner.CloneAttributes(extremeLemma.Attributes), extremeLemma);
 01969              extraMember = extremeLemma.PrefixLemma;
 01970            }
 1971
 01972            extraMember.InheritVisibility(m, false);
 01973            members.Add(extraName.Value, extraMember);
 67611974          } else if (m is Function f && f.ByMethodBody != null) {
 01975            RegisterByMethod(f, cl);
 01976          }
 67611977        } else if (m is Constructor && !((Constructor)m).HasName) {
 01978          reporter.Error(MessageSource.Resolver, m, "More than one anonymous constructor");
 01979        } else {
 01980          reporter.Error(MessageSource.Resolver, m, "Duplicate member name: {0}", m.Name);
 01981        }
 67611982      }
 30711983    }
 1984
 01985    void RegisterByMethod(Function f, TopLevelDeclWithMembers cl) {
 1986      Contract.Requires(f != null && f.ByMethodBody != null);
 1987
 01988      var tok = f.ByMethodTok;
 01989      var resultVar = f.Result ?? new Formal(tok, "#result", f.ResultType, false, false, null);
 01990      var r = Expression.CreateIdentExpr(resultVar);
 01991      var receiver = f.IsStatic ? (Expression)new StaticReceiverExpr(tok, cl, true) : new ImplicitThisExpr(tok);
 01992      var fn = new FunctionCallExpr(tok, f.Name, receiver, tok, tok, f.Formals.ConvertAll(Expression.CreateIdentExpr));
 01993      var post = new AttributedExpression(new BinaryExpr(tok, BinaryExpr.Opcode.Eq, r, fn));
 01994      var method = new Method(f.RangeToken, f.NameNode, f.HasStaticKeyword, false, f.TypeArgs,
 01995        f.Formals, new List<Formal>() { resultVar },
 01996        f.Req, new Specification<FrameExpression>(new List<FrameExpression>(), null), new List<AttributedExpression>() {
 01997        f.ByMethodBody, f.Attributes, null, true);
 01998      Contract.Assert(f.ByMethodDecl == null);
 01999      method.InheritVisibility(f);
 02000      method.FunctionFromWhichThisIsByMethodDecl = f;
 02001      f.ByMethodDecl = method;
 02002    }
 2003
 2004    private ModuleSignature MakeAbstractSignature(ModuleSignature p, string Name, int Height,
 2005      Dictionary<ModuleDefinition, ModuleSignature> mods,
 02006      Dictionary<ModuleDefinition, ModuleDefinition> compilationModuleClones) {
 2007      Contract.Requires(p != null);
 2008      Contract.Requires(Name != null);
 2009      Contract.Requires(mods != null);
 2010      Contract.Requires(compilationModuleClones != null);
 02011      var errCount = reporter.Count(ErrorLevel.Error);
 2012
 02013      var mod = new ModuleDefinition(RangeToken.NoToken, new Name(Name + ".Abs"), new List<IToken>(), true, true, null, 
 02014        false,
 02015        p.ModuleDef.IsToBeVerified, p.ModuleDef.IsToBeCompiled);
 02016      mod.Height = Height;
 02017      bool hasDefaultClass = false;
 02018      foreach (var kv in p.TopLevels) {
 02019        hasDefaultClass = kv.Value is DefaultClassDecl || hasDefaultClass;
 02020        if (!(kv.Value is NonNullTypeDecl)) {
 02021          var clone = CloneDeclaration(p.VisibilityScope, kv.Value, mod, mods, Name, compilationModuleClones);
 02022          mod.TopLevelDecls.Add(clone);
 02023        }
 02024      }
 2025
 02026      if (!hasDefaultClass) {
 02027        DefaultClassDecl cl = new DefaultClassDecl(mod, p.StaticMembers.Values.ToList());
 02028        mod.TopLevelDecls.Add(CloneDeclaration(p.VisibilityScope, cl, mod, mods, Name, compilationModuleClones));
 02029      }
 2030
 02031      var sig = RegisterTopLevelDecls(mod, true);
 02032      sig.Refines = p.Refines;
 02033      sig.CompileSignature = p;
 02034      sig.IsAbstract = p.IsAbstract;
 02035      mods.Add(mod, sig);
 02036      var good = ResolveModuleDefinition(mod, sig);
 02037      if (good && reporter.Count(ErrorLevel.Error) == errCount) {
 02038        mod.SuccessfullyResolved = true;
 02039      }
 2040
 02041      return sig;
 02042    }
 2043
 2044    TopLevelDecl CloneDeclaration(VisibilityScope scope, TopLevelDecl d, ModuleDefinition m,
 2045      Dictionary<ModuleDefinition, ModuleSignature> mods, string Name,
 02046      Dictionary<ModuleDefinition, ModuleDefinition> compilationModuleClones) {
 2047      Contract.Requires(d != null);
 2048      Contract.Requires(m != null);
 2049      Contract.Requires(mods != null);
 2050      Contract.Requires(Name != null);
 2051      Contract.Requires(compilationModuleClones != null);
 2052
 02053      if (d is AbstractModuleDecl) {
 02054        var abs = (AbstractModuleDecl)d;
 02055        var sig = MakeAbstractSignature(abs.OriginalSignature, Name + "." + abs.Name, abs.Height, mods,
 02056          compilationModuleClones);
 02057        var a = new AbstractModuleDecl(abs.RangeToken, abs.QId, abs.NameNode, m, abs.Opened, abs.Exports);
 02058        a.Signature = sig;
 02059        a.OriginalSignature = abs.OriginalSignature;
 02060        return a;
 02061      } else {
 02062        return new AbstractSignatureCloner(scope).CloneDeclaration(d, m);
 2063      }
 02064    }
 2065
 2066    // Returns the resolved Module declaration corresponding to the qualified module id
 2067    // Requires the root to have been resolved
 2068    // Issues an error and returns null if the path is not valid
 02069    public ModuleDecl ResolveModuleQualifiedId(ModuleDecl root, ModuleQualifiedId qid, ErrorReporter reporter) {
 2070
 2071      Contract.Requires(qid != null);
 2072      Contract.Requires(qid.Path.Count > 0);
 2073
 02074      List<Name> Path = qid.Path;
 02075      ModuleDecl decl = root;
 2076      ModuleSignature p;
 02077      for (int k = 1; k < Path.Count; k++) {
 02078        if (decl is LiteralModuleDecl) {
 02079          p = ((LiteralModuleDecl)decl).DefaultExport;
 02080          if (p == null) {
 02081            reporter.Error(MessageSource.Resolver, Path[k],
 02082              ModuleNotFoundErrorMessage(k, Path, $" because {decl.Name} does not have a default export"));
 02083            return null;
 2084          }
 02085        } else {
 02086          p = decl.Signature;
 02087        }
 2088
 02089        var tld = p.TopLevels.GetValueOrDefault(Path[k].Value, null);
 02090        if (!(tld is ModuleDecl dd)) {
 02091          if (decl.Signature.ModuleDef == null) {
 02092            reporter.Error(MessageSource.Resolver, Path[k],
 02093              ModuleNotFoundErrorMessage(k, Path, " because of previous error"));
 02094          } else {
 02095            reporter.Error(MessageSource.Resolver, Path[k], ModuleNotFoundErrorMessage(k, Path));
 02096          }
 02097          return null;
 2098        }
 2099
 2100        // Any aliases along the qualified path ought to be already resolved,
 2101        // else the modules are not being resolved in the right order
 02102        if (dd is AliasModuleDecl amd) {
 02103          Contract.Assert(amd.Signature != null);
 02104        }
 02105        decl = dd;
 02106      }
 2107
 02108      return decl;
 02109    }
 2110
 2111
 2112    public bool ResolveExport(ModuleDecl alias, ModuleDefinition parent, ModuleQualifiedId qid,
 02113      List<IToken> Exports, out ModuleSignature p, ErrorReporter reporter) {
 2114      Contract.Requires(qid != null);
 2115      Contract.Requires(qid.Path.Count > 0);
 2116      Contract.Requires(Exports != null);
 2117
 02118      ModuleDecl root = qid.Root;
 02119      ModuleDecl decl = ResolveModuleQualifiedId(root, qid, reporter);
 02120      if (decl == null) {
 02121        p = null;
 02122        return false;
 2123      }
 02124      p = decl.Signature;
 02125      if (Exports.Count == 0) {
 02126        if (p.ExportSets.Count == 0) {
 02127          if (decl is LiteralModuleDecl) {
 02128            p = ((LiteralModuleDecl)decl).DefaultExport;
 02129          } else {
 2130            // p is OK
 02131          }
 02132        } else {
 02133          var m = p.ExportSets.GetValueOrDefault(decl.Name, null);
 02134          if (m == null) {
 2135            // no default view is specified.
 02136            reporter.Error(MessageSource.Resolver, qid.rootToken(), "no default export set declared in module: {0}", dec
 02137            return false;
 2138          }
 02139          p = m.AccessibleSignature();
 02140        }
 02141      } else {
 2142        ModuleExportDecl pp;
 02143        if (decl.Signature.ExportSets.TryGetValue(Exports[0].val, out pp)) {
 02144          p = pp.AccessibleSignature();
 02145        } else {
 02146          reporter.Error(MessageSource.Resolver, Exports[0], "no export set '{0}' in module '{1}'", Exports[0].val, decl
 02147          p = null;
 02148          return false;
 2149        }
 2150
 02151        foreach (IToken export in Exports.Skip(1)) {
 02152          if (decl.Signature.ExportSets.TryGetValue(export.val, out pp)) {
 02153            Contract.Assert(Object.ReferenceEquals(p.ModuleDef, pp.Signature.ModuleDef));
 02154            ModuleSignature merged = MergeSignature(p, pp.Signature);
 02155            merged.ModuleDef = pp.Signature.ModuleDef;
 02156            if (p.CompileSignature != null) {
 02157              Contract.Assert(pp.Signature.CompileSignature != null);
 02158              merged.CompileSignature = MergeSignature(p.CompileSignature, pp.Signature.CompileSignature);
 02159            } else {
 02160              Contract.Assert(pp.Signature.CompileSignature == null);
 02161            }
 02162            p = merged;
 02163          } else {
 02164            reporter.Error(MessageSource.Resolver, export, "no export set {0} in module {1}", export.val, decl.Name);
 02165            p = null;
 02166            return false;
 2167          }
 02168        }
 02169      }
 02170      return true;
 02171    }
 2172
 8882173    public void RevealAllInScope(List<TopLevelDecl> declarations, VisibilityScope scope) {
 238112174      foreach (TopLevelDecl d in declarations) {
 70492175        d.AddVisibilityScope(scope, false);
 101202176        if (d is TopLevelDeclWithMembers) {
 30712177          var cl = (TopLevelDeclWithMembers)d;
 294962178          foreach (var mem in cl.Members) {
 135222179            if (!mem.ScopeIsInherited) {
 67612180              mem.AddVisibilityScope(scope, false);
 67612181            }
 67612182          }
 30712183          var nnd = (cl as ClassDecl)?.NonNullTypeDecl;
 36832184          if (nnd != null) {
 6122185            nnd.AddVisibilityScope(scope, false);
 6122186          }
 30712187        }
 70492188      }
 8882189    }
 2190
 5822191    public void ResolveTopLevelDecls_Signatures(ModuleDefinition def, ModuleSignature sig, List<TopLevelDecl/*!*/>/*!*/ 
 2192      Contract.Requires(declarations != null);
 2193      Contract.Requires(datatypeDependencies != null);
 2194      Contract.Requires(codatatypeDependencies != null);
 5822195      RevealAllInScope(declarations, def.VisibilityScope);
 2196
 2197      /* Augment the scoping environment for the current module*/
 50732198      foreach (TopLevelDecl d in declarations) {
 11092199        if (d is ModuleDecl && !(d is ModuleExportDecl)) {
 02200          var decl = (ModuleDecl)d;
 02201          moduleInfo.VisibilityScope.Augment(decl.AccessibleSignature().VisibilityScope);
 02202          sig.VisibilityScope.Augment(decl.AccessibleSignature().VisibilityScope);
 02203        }
 11092204      }
 2205      /*if (sig.Refines != null) {
 2206        moduleInfo.VisibilityScope.Augment(sig.Refines.VisibilityScope);
 2207        sig.VisibilityScope.Augment(sig.Refines.VisibilityScope);
 2208      }*/
 2209
 5822210      var typeRedirectionDependencies = new Graph<RedirectingTypeDecl>();  // this concerns the type directions, not the
 50732211      foreach (TopLevelDecl d in declarations) {
 11092212        Contract.Assert(d != null);
 11092213        allTypeParameters.PushMarker();
 11092214        ResolveTypeParameters(d.TypeArgs, true, d);
 11092215        if (d is TypeSynonymDecl) {
 02216          var dd = (TypeSynonymDecl)d;
 02217          ResolveType(dd.tok, dd.Rhs, dd, ResolveTypeOptionEnum.AllowPrefix, dd.TypeArgs);
 02218          dd.Rhs.ForeachTypeComponent(ty => {
 02219            var s = ty.AsRedirectingType;
 02220            if (s != null && s != dd) {
 02221              typeRedirectionDependencies.AddEdge(dd, s);
 02222            }
 02223          });
 11092224        } else if (d is NewtypeDecl) {
 02225          var dd = (NewtypeDecl)d;
 02226          ResolveType(dd.tok, dd.BaseType, dd, ResolveTypeOptionEnum.DontInfer, null);
 02227          dd.BaseType.ForeachTypeComponent(ty => {
 02228            var s = ty.AsRedirectingType;
 02229            if (s != null && s != dd) {
 02230              typeRedirectionDependencies.AddEdge(dd, s);
 02231            }
 02232          });
 02233          ResolveClassMemberTypes(dd);
 11092234        } else if (d is IteratorDecl) {
 02235          ResolveIteratorSignature((IteratorDecl)d);
 11092236        } else if (d is ModuleDecl) {
 02237          var decl = (ModuleDecl)d;
 02238          if (!def.IsAbstract && decl is AliasModuleDecl am && decl.Signature.IsAbstract) {
 02239            reporter.Error(MessageSource.Resolver, am.TargetQId.rootToken(), "a compiled module ({0}) is not allowed to 
 02240          }
 16362241        } else if (d is DatatypeDecl) {
 5272242          var dd = (DatatypeDecl)d;
 5272243          ResolveCtorTypes(dd, datatypeDependencies, codatatypeDependencies);
 5272244          ResolveClassMemberTypes(dd);
 11092245        } else {
 5822246          ResolveClassMemberTypes((TopLevelDeclWithMembers)d);
 5822247        }
 11092248        allTypeParameters.PopMarker();
 11092249      }
 2250
 2251      // Resolve the parent-trait types and fill in .ParentTraitHeads
 5822252      var prevErrorCount = reporter.Count(ErrorLevel.Error);
 5822253      var parentRelation = new Graph<TopLevelDeclWithMembers>();
 50732254      foreach (TopLevelDecl d in declarations) {
 22182255        if (d is TopLevelDeclWithMembers cl) {
 11092256          ResolveParentTraitTypes(cl, parentRelation);
 11092257        }
 11092258      }
 2259      // Check for cycles among parent traits
 17462260      foreach (var cycle in parentRelation.AllCycles()) {
 02261        ReportCycleError(cycle, m => m.tok, m => m.Name, "trait definitions contain a cycle");
 02262      }
 11642263      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 2264        // Register the trait members in the classes that inherit them
 50732265        foreach (TopLevelDecl d in declarations) {
 22182266          if (d is TopLevelDeclWithMembers cl) {
 11092267            RegisterInheritedMembers(cl);
 11092268          }
 11092269        }
 5822270      }
 11642271      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 2272        // Now that all traits have been resolved, let classes inherit the trait members
 50732273        foreach (var d in declarations) {
 22182274          if (d is TopLevelDeclWithMembers cl) {
 11092275            InheritedTraitMembers(cl);
 11092276          }
 11092277        }
 5822278      }
 2279
 2280      // perform acyclicity test on type synonyms
 17462281      foreach (var cycle in typeRedirectionDependencies.AllCycles()) {
 02282        ReportCycleError(cycle, rtd => rtd.tok, rtd => rtd.Name, "cycle among redirecting types (newtypes, subset types,
 02283      }
 5822284    }
 2285
 02286    public static readonly List<NativeType> NativeTypes = new List<NativeType>() {
 02287      new NativeType("byte", 0, 0x100, 8, NativeType.Selection.Byte),
 02288      new NativeType("sbyte", -0x80, 0x80, 0, NativeType.Selection.SByte),
 02289      new NativeType("ushort", 0, 0x1_0000, 16, NativeType.Selection.UShort),
 02290      new NativeType("short", -0x8000, 0x8000, 0, NativeType.Selection.Short),
 02291      new NativeType("uint", 0, 0x1_0000_0000, 32, NativeType.Selection.UInt),
 02292      new NativeType("int", -0x8000_0000, 0x8000_0000, 0, NativeType.Selection.Int),
 02293      new NativeType("number", -0x1f_ffff_ffff_ffff, 0x20_0000_0000_0000, 0, NativeType.Selection.Number),  // JavaScrip
 02294      new NativeType("ulong", 0, new BigInteger(0x1_0000_0000) * new BigInteger(0x1_0000_0000), 64, NativeType.Selection
 02295      new NativeType("long", Int64.MinValue, 0x8000_0000_0000_0000, 0, NativeType.Selection.Long),
 02296    };
 2297
 2298    public void ResolveTopLevelDecls_Core(List<TopLevelDecl> declarations,
 2299      Graph<IndDatatypeDecl> datatypeDependencies, Graph<CoDatatypeDecl> codatatypeDependencies,
 8882300      string moduleName, bool isAnExport = false) {
 2301
 2302      Contract.Requires(declarations != null);
 2303      Contract.Requires(cce.NonNullElements(datatypeDependencies.GetVertices()));
 2304      Contract.Requires(cce.NonNullElements(codatatypeDependencies.GetVertices()));
 2305      Contract.Requires(AllTypeConstraints.Count == 0);
 2306
 2307      Contract.Ensures(AllTypeConstraints.Count == 0);
 2308
 8882309      int prevErrorCount = reporter.Count(ErrorLevel.Error);
 2310
 2311      // ---------------------------------- Pass 0 ----------------------------------
 2312      // This pass:
 2313      // * resolves names, introduces (and may solve) type constraints
 2314      // * checks that all types were properly inferred
 2315      // * fills in .ResolvedOp fields
 2316      // * perform substitution for DefaultValueExpression's
 2317      // ----------------------------------------------------------------------------
 2318
 8882319      if (Options.Get(CommonOptionBag.TypeSystemRefresh)) {
 2320        // Resolve all names and infer types.
 02321        var preTypeResolver = new PreTypeResolver(this);
 02322        preTypeResolver.ResolveDeclarations(declarations, moduleName);
 2323
 02324        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 02325          var u = new UnderspecificationDetector(this);
 02326          u.Check(declarations);
 02327        }
 2328
 02329        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 02330          new PreTypeToTypeVisitor().VisitDeclarations(declarations);
 02331        }
 2332
 8882333      } else {
 2334        // Resolve all names and infer types. These two are done together, because name resolution depends on having typ
 2335        // and type inference depends on having resolved names.
 2336        // The task is first performed for (the constraints of) newtype declarations, (the constraints of) subset type d
 2337        // (the right-hand sides of) const declarations, because type resolution sometimes needs to know the base type o
 2338        // and needs to know the type of const fields. Doing these declarations increases the chances the right informat
 2339        // in time.
 2340        // Once the task is done for these newtype/subset-type/const parts, the task continues with everything else.
 8882341        ResolveNamesAndInferTypes(declarations, true);
 8882342        ResolveNamesAndInferTypes(declarations, false);
 8882343      }
 2344
 2345      // Check that all types have been determined. During this process, also fill in all .ResolvedOp fields.
 17762346      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 8882347        var checkTypeInferenceVisitor = new CheckTypeInferenceVisitor(this);
 8882348        checkTypeInferenceVisitor.VisitDeclarations(declarations);
 8882349      }
 2350
 2351      // Substitute for DefaultValueExpression's
 8882352      FillInDefaultValueExpressions();
 2353
 2354      // ---------------------------------- Pass 1 ----------------------------------
 2355      // This pass does the following:
 2356      // * desugar functions used in reads clauses
 2357      // * compute .BodySurrogate for body-less loops
 2358      // * discovers bounds
 2359      // * builds the module's call graph.
 2360      // * compute and checks ghosts (this makes use of bounds discovery, as done above)
 2361      // * for newtypes, figure out native types
 2362      // * for datatypes, check that shared destructors are in agreement in ghost matters
 2363      // * for functions and methods, determine tail recursion
 2364      // ----------------------------------------------------------------------------
 2365
 2366      // Discover bounds. These are needed later to determine if certain things are ghost or compiled,
 2367      // and thus this should be done before building the call graph.
 2368      // The BoundsDiscoveryVisitor also desugars FrameExpressions, so that bounds discovery can
 2369      // apply to the desugared versions.
 2370      // This pass also computes body surrogates for body-less loops, which is a bit like desugaring
 2371      // such loops.
 17462372      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 8582373        var boundsDiscoveryVisitor = new BoundsDiscoveryVisitor(reporter);
 8582374        boundsDiscoveryVisitor.VisitDeclarations(declarations);
 8582375      }
 2376
 17462377      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 8582378        CallGraphBuilder.Build(declarations, reporter);
 8582379      }
 2380
 2381      // Compute ghost interests, figure out native types, check agreement among datatype destructors, and determine tai
 17462382      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 92582383        foreach (TopLevelDecl d in declarations) {
 22282384          if (d is IteratorDecl) {
 02385            var iter = (IteratorDecl)d;
 02386            iter.SubExpressions.Iter(e => CheckExpression(e, this, iter));
 02387            if (iter.Body != null) {
 02388              ComputeGhostInterest(iter.Body, false, null, iter);
 02389              CheckExpression(iter.Body, this, iter);
 02390            }
 2391
 28402392          } else if (d is SubsetTypeDecl subsetTypeDecl) {
 6122393            Contract.Assert(subsetTypeDecl.Constraint != null);
 6122394            CheckExpression(subsetTypeDecl.Constraint, this, new CodeContextWrapper(subsetTypeDecl, true));
 6122395            subsetTypeDecl.ConstraintIsCompilable =
 6122396              ExpressionTester.CheckIsCompilable(Options, null, subsetTypeDecl.Constraint, new CodeContextWrapper(subset
 6122397            subsetTypeDecl.CheckedIfConstraintIsCompilable = true;
 2398
 6122399            if (subsetTypeDecl.Witness != null) {
 02400              CheckExpression(subsetTypeDecl.Witness, this, new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.Witnes
 02401              if (subsetTypeDecl.WitnessKind == SubsetTypeDecl.WKind.Compiled) {
 02402                var codeContext = new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.WitnessKind == SubsetTypeDecl.WK
 02403                ExpressionTester.CheckIsCompilable(Options, this, subsetTypeDecl.Witness, codeContext);
 02404              }
 02405            }
 2406
 22282407          } else if (d is NewtypeDecl newtypeDecl) {
 02408            if (newtypeDecl.Var != null) {
 02409              Contract.Assert(newtypeDecl.Constraint != null);
 02410              CheckExpression(newtypeDecl.Constraint, this, new CodeContextWrapper(newtypeDecl, true));
 02411              if (newtypeDecl.Witness != null) {
 02412                CheckExpression(newtypeDecl.Witness, this, new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind =
 02413              }
 02414            }
 02415            if (newtypeDecl.Witness != null && newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Compiled) {
 02416              var codeContext = new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Ghos
 02417              ExpressionTester.CheckIsCompilable(Options, this, newtypeDecl.Witness, codeContext);
 02418            }
 2419
 02420            FigureOutNativeType(newtypeDecl);
 2421
 20682422          } else if (d is DatatypeDecl) {
 4522423            var dd = (DatatypeDecl)d;
 61922424            foreach (var member in classMembers[dd].Values) {
 16122425              var dtor = member as DatatypeDestructor;
 23422426              if (dtor != null) {
 7302427                var rolemodel = dtor.CorrespondingFormals[0];
 14602428                for (int i = 1; i < dtor.CorrespondingFormals.Count; i++) {
 02429                  var other = dtor.CorrespondingFormals[i];
 02430                  if (rolemodel.IsGhost != other.IsGhost) {
 02431                    reporter.Error(MessageSource.Resolver, other,
 02432                      "shared destructors must agree on whether or not they are ghost, but '{0}' is {1} in constructor '
 02433                      rolemodel.Name,
 02434                      rolemodel.IsGhost ? "ghost" : "non-ghost", dtor.EnclosingCtors[0].Name,
 02435                      other.IsGhost ? "ghost" : "non-ghost", dtor.EnclosingCtors[i].Name);
 02436                  }
 02437                }
 7302438              }
 16122439            }
 40022440            foreach (var ctor in dd.Ctors) {
 8822441              CheckParameterDefaultValuesAreCompilable(ctor.Formals, dd);
 8822442            }
 4522443          }
 2444
 38442445          if (d is TopLevelDeclWithMembers cl) {
 16162446            ResolveClassMembers_Pass1(cl);
 16162447          }
 22282448        }
 8582449      }
 2450
 2451      // ---------------------------------- Pass 2 ----------------------------------
 2452      // This pass fills in various additional information.
 2453      // * Subset type in comprehensions have a compilable constraint
 2454      // * Postconditions and bodies of prefix lemmas
 2455      // * Compute postconditions and statement body of prefix lemmas
 2456      // * Perform the stratosphere check on inductive datatypes, and compute to what extent the inductive datatypes req
 2457      // * Set the SccRepr field of codatatypes
 2458      // * Perform the guardedness check on co-datatypes
 2459      // * Do datatypes and type synonyms until a fixpoint is reached, same for functions and methods
 2460      // * Check that functions claiming to be abstemious really are
 2461      // * Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
 2462      // * Extreme predicate recursivity checks
 2463      // * Verify that subset constraints are compilable if necessary
 2464      // ----------------------------------------------------------------------------
 2465
 17462466      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2467        // fill in the postconditions and bodies of prefix lemmas
 8582468        FillInPostConditionsAndBodiesOfPrefixLemmas(declarations);
 8582469      }
 2470
 2471      // Perform the stratosphere check on inductive datatypes, and compute to what extent the inductive datatypes requi
 42452472      foreach (var dtd in datatypeDependencies.TopologicallySortedComponents()) {
 10542473        if (datatypeDependencies.GetSCCRepresentative(dtd) == dtd) {
 2474          // do the following check once per SCC, so call it on each SCC representative
 5272475          SccStratosphereCheck(dtd, datatypeDependencies);
 5272476          DetermineEqualitySupport(dtd, datatypeDependencies);
 5272477        }
 5272478      }
 2479
 2480      // Set the SccRepr field of codatatypes
 26642481      foreach (var repr in codatatypeDependencies.TopologicallySortedComponents()) {
 02482        foreach (var codt in codatatypeDependencies.GetSCC(repr)) {
 02483          codt.SscRepr = repr;
 02484        }
 02485      }
 2486
 17462487      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {  // because CheckCoCalls requires the given expression t
 2488        // Perform the guardedness check on co-datatypes
 25742489        foreach (var repr in ModuleDefinition.AllFunctionSCCs(declarations)) {
 02490          var module = repr.EnclosingModule;
 02491          bool dealsWithCodatatypes = false;
 02492          foreach (var m in module.CallGraph.GetSCC(repr)) {
 02493            var f = m as Function;
 02494            if (f != null && f.ResultType.InvolvesCoDatatype) {
 02495              dealsWithCodatatypes = true;
 02496              break;
 2497            }
 02498          }
 02499          var coCandidates = new List<CoCallResolution.CoCallInfo>();
 02500          var hasIntraClusterCallsInDestructiveContexts = false;
 02501          foreach (var m in module.CallGraph.GetSCC(repr)) {
 02502            var f = m as Function;
 02503            if (f != null && f.Body != null) {
 02504              var checker = new CoCallResolution(f, dealsWithCodatatypes);
 02505              checker.CheckCoCalls(f.Body);
 02506              coCandidates.AddRange(checker.FinalCandidates);
 02507              hasIntraClusterCallsInDestructiveContexts |= checker.HasIntraClusterCallsInDestructiveContexts;
 02508            } else if (f == null) {
 2509              // the SCC contains a method, which we always consider to be a destructive context
 02510              hasIntraClusterCallsInDestructiveContexts = true;
 02511            }
 02512          }
 02513          if (coCandidates.Count != 0) {
 02514            if (hasIntraClusterCallsInDestructiveContexts) {
 02515              foreach (var c in coCandidates) {
 02516                c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseRecursiveCallsInDestructiveContext;
 02517              }
 02518            } else {
 02519              foreach (var c in coCandidates) {
 02520                c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.Yes;
 02521                c.EnclosingCoConstructor.IsCoCall = true;
 02522                reporter.Info(MessageSource.Resolver, c.CandidateCall.tok, "co-recursive call");
 02523              }
 2524              // Finally, fill in the CoClusterTarget field
 2525              // Start by setting all the CoClusterTarget fields to CoRecursiveTargetAllTheWay.
 02526              foreach (var m in module.CallGraph.GetSCC(repr)) {
 02527                var f = (Function)m;  // the cast is justified on account of that we allow co-recursive calls only in cl
 02528                f.CoClusterTarget = Function.CoCallClusterInvolvement.CoRecursiveTargetAllTheWay;
 02529              }
 2530              // Then change the field to IsMutuallyRecursiveTarget whenever we see a non-self recursive non-co-recursiv
 02531              foreach (var m in module.CallGraph.GetSCC(repr)) {
 02532                var f = (Function)m;  // cast is justified just like above
 02533                foreach (var call in f.AllCalls) {
 02534                  if (call.CoCall != FunctionCallExpr.CoCallResolution.Yes && call.Function != f && ModuleDefinition.InS
 02535                    call.Function.CoClusterTarget = Function.CoCallClusterInvolvement.IsMutuallyRecursiveTarget;
 02536                  }
 02537                }
 02538              }
 02539            }
 02540          }
 02541        }
 2542        // Inferred required equality support for datatypes and type synonyms, and for Function and Method signatures.
 2543        // First, do datatypes and type synonyms until a fixpoint is reached.
 2544        bool inferredSomething;
 8582545        do {
 8582546          inferredSomething = false;
 92582547          foreach (var d in declarations) {
 22282548            if (Attributes.Contains(d.Attributes, "_provided")) {
 2549              // Don't infer required-equality-support for the type parameters, since there are
 2550              // scopes that see the name of the declaration but not its body.
 26802551            } else if (d is DatatypeDecl) {
 4522552              var dt = (DatatypeDecl)d;
 27422553              foreach (var tp in dt.TypeArgs) {
 9242554                if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2555                  // here's our chance to infer the need for equality support
 40322556                  foreach (var ctor in dt.Ctors) {
 42362557                    foreach (var arg in ctor.Formals) {
 5302558                      if (InferRequiredEqualitySupport(tp, arg.Type)) {
 02559                        tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02560                        inferredSomething = true;
 02561                        goto DONE_DT;  // break out of the doubly-nested loop
 2562                      }
 5302563                    }
 8822564                  }
 9242565                DONE_DT:;
 4622566                }
 4622567              }
 28402568            } else if (d is TypeSynonymDecl) {
 6122569              var syn = (TypeSynonymDecl)d;
 27542570              foreach (var tp in syn.TypeArgs) {
 6122571                if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2572                  // here's our chance to infer the need for equality support
 3062573                  if (InferRequiredEqualitySupport(tp, syn.Rhs)) {
 02574                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02575                    inferredSomething = true;
 02576                  }
 3062577                }
 3062578              }
 6122579            }
 22282580          }
 17162581        } while (inferredSomething);
 2582        // Now do it for Function and Method signatures.
 92582583        foreach (var d in declarations) {
 22282584          if (d is IteratorDecl) {
 02585            var iter = (IteratorDecl)d;
 02586            var done = false;
 02587            var nonnullIter = iter.NonNullTypeDecl;
 02588            Contract.Assert(nonnullIter.TypeArgs.Count == iter.TypeArgs.Count);
 02589            for (var i = 0; i < iter.TypeArgs.Count; i++) {
 02590              var tp = iter.TypeArgs[i];
 02591              var correspondingNonnullIterTypeParameter = nonnullIter.TypeArgs[i];
 02592              if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2593                // here's our chance to infer the need for equality support
 02594                foreach (var p in iter.Ins) {
 02595                  if (InferRequiredEqualitySupport(tp, p.Type)) {
 02596                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02597                    correspondingNonnullIterTypeParameter.Characteristics.EqualitySupport = TypeParameter.EqualitySuppor
 02598                    done = true;
 02599                    break;
 2600                  }
 02601                }
 02602                foreach (var p in iter.Outs) {
 02603                  if (done) {
 02604                    break;
 2605                  }
 2606
 02607                  if (InferRequiredEqualitySupport(tp, p.Type)) {
 02608                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02609                    correspondingNonnullIterTypeParameter.Characteristics.EqualitySupport = TypeParameter.EqualitySuppor
 02610                    break;
 2611                  }
 02612                }
 02613              }
 02614            }
 33922615          } else if (d is ClassDecl) {
 11642616            var cl = (ClassDecl)d;
 189482617            foreach (var member in cl.Members) {
 103042618              if (!member.IsGhost) {
 51522619                if (member is Function) {
 02620                  var f = (Function)member;
 02621                  foreach (var tp in f.TypeArgs) {
 02622                    if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2623                      // here's our chance to infer the need for equality support
 02624                      if (InferRequiredEqualitySupport(tp, f.ResultType)) {
 02625                        tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02626                      } else {
 02627                        foreach (var p in f.Formals) {
 02628                          if (InferRequiredEqualitySupport(tp, p.Type)) {
 02629                            tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02630                            break;
 2631                          }
 02632                        }
 02633                      }
 02634                    }
 02635                  }
 99982636                } else if (member is Method) {
 48462637                  var m = (Method)member;
 48462638                  bool done = false;
 178502639                  foreach (var tp in m.TypeArgs) {
 22082640                    if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2641                      // here's our chance to infer the need for equality support
 115922642                      foreach (var p in m.Ins) {
 27602643                        if (InferRequiredEqualitySupport(tp, p.Type)) {
 02644                          tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02645                          done = true;
 02646                          break;
 2647                        }
 27602648                      }
 82802649                      foreach (var p in m.Outs) {
 16562650                        if (done) {
 02651                          break;
 2652                        }
 2653
 16562654                        if (InferRequiredEqualitySupport(tp, p.Type)) {
 02655                          tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02656                          break;
 2657                        }
 16562658                      }
 11042659                    }
 11042660                  }
 48462661                }
 51522662              }
 51522663            }
 11642664          }
 22282665        }
 2666        // Check that functions claiming to be abstemious really are, and check that 'older' parameters are used only wh
 25742667        foreach (var fn in ModuleDefinition.AllFunctions(declarations)) {
 02668          new Abstemious(reporter).Check(fn);
 02669          CheckOlderParameters(fn);
 02670        }
 2671        // Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
 2672        // Note that this check can only be done after determining which expressions are ghosts.
 92582673        foreach (var d in declarations) {
 81282674          for (var attr = d.Attributes; attr != null; attr = attr.Prev) {
 18362675            attr.Args.Iter(e => CheckTypeCharacteristics_Expr(e, true));
 12242676          }
 2677
 22282678          if (d is IteratorDecl) {
 02679            var iter = (IteratorDecl)d;
 02680            foreach (var p in iter.Ins) {
 02681              CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02682            }
 02683            foreach (var p in iter.Outs) {
 02684              CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02685            }
 02686            if (iter.Body != null) {
 02687              CheckTypeCharacteristics_Stmt(iter.Body, false);
 02688            }
 33922689          } else if (d is ClassDecl) {
 11642690            var cl = (ClassDecl)d;
 34922691            foreach (var parentTrait in cl.ParentTraits) {
 02692              CheckTypeCharacteristics_Type(cl.tok, parentTrait, false);
 02693            }
 26802694          } else if (d is DatatypeDecl) {
 4522695            var dt = (DatatypeDecl)d;
 40022696            foreach (var ctor in dt.Ctors) {
 48362697              foreach (var p in ctor.Formals) {
 7302698                CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 7302699              }
 8822700            }
 16762701          } else if (d is TypeSynonymDecl) {
 6122702            var syn = (TypeSynonymDecl)d;
 6122703            CheckTypeCharacteristics_Type(syn.tok, syn.Rhs, false);
 12242704            if (!isAnExport) {
 6122705              if (syn.SupportsEquality && !syn.Rhs.SupportsEquality) {
 02706                reporter.Error(MessageSource.Resolver, syn.tok, "type '{0}' declared as supporting equality, but the RHS
 02707                  syn.Name, syn.Rhs);
 02708              }
 6122709              if (syn.Characteristics.IsNonempty && !syn.Rhs.IsNonempty) {
 02710                reporter.Error(MessageSource.Resolver, syn.tok, "type '{0}' declared as being nonempty, but the RHS type
 02711                  syn.Name, syn.Rhs);
 6122712              } else if (syn.Characteristics.HasCompiledValue && !syn.Rhs.HasCompilableValue) {
 02713                reporter.Error(MessageSource.Resolver, syn.tok,
 02714                  "type '{0}' declared as auto-initialization type, but the RHS type ({1}) does not support auto-initial
 02715              }
 6122716              if (syn.Characteristics.ContainsNoReferenceTypes && syn.Rhs.MayInvolveReferences) {
 02717                reporter.Error(MessageSource.Resolver, syn.tok,
 02718                  "type '{0}' declared as containing no reference types, but the RHS type ({1}) may contain reference ty
 02719              }
 6122720            }
 6122721          }
 2722
 28402723          if (d is RedirectingTypeDecl) {
 6122724            var rtd = (RedirectingTypeDecl)d;
 12242725            if (rtd.Constraint != null) {
 6122726              CheckTypeCharacteristics_Expr(rtd.Constraint, true);
 6122727            }
 6122728            if (rtd.Witness != null) {
 02729              CheckTypeCharacteristics_Expr(rtd.Witness, rtd.WitnessKind == SubsetTypeDecl.WKind.Ghost);
 02730            }
 6122731          }
 2732
 38442733          if (d is TopLevelDeclWithMembers) {
 16162734            var cl = (TopLevelDeclWithMembers)d;
 203042735            foreach (var member in cl.Members) {
 54582736              if (member is Field) {
 3062737                var f = (Field)member;
 3062738                CheckTypeCharacteristics_Type(f.tok, f.Type, f.IsGhost);
 3062739                if (f is ConstantField cf && cf.Rhs != null) {
 02740                  CheckTypeCharacteristics_Expr(cf.Rhs, cf.IsGhost);
 02741                }
 51522742              } else if (member is Function) {
 02743                var f = (Function)member;
 02744                foreach (var p in f.Formals) {
 02745                  CheckTypeCharacteristics_Type(p.tok, p.Type, f.IsGhost || p.IsGhost);
 02746                }
 02747                if (f.Body != null) {
 02748                  CheckTypeCharacteristics_Expr(f.Body, f.IsGhost);
 02749                }
 96922750              } else if (member is Method) {
 48462751                var m = (Method)member;
 448502752                foreach (var p in m.Ins) {
 101042753                  CheckTypeCharacteristics_Type(p.tok, p.Type, m.IsGhost || p.IsGhost);
 101042754                }
 313142755                foreach (var p in m.Outs) {
 55922756                  CheckTypeCharacteristics_Type(p.tok, p.Type, m.IsGhost || p.IsGhost);
 55922757                }
 96922758                if (m.Body != null) {
 48462759                  CheckTypeCharacteristics_Stmt(m.Body, m.IsGhost);
 48462760                }
 48462761              }
 51522762            }
 16162763          }
 22282764        }
 2765        // Check that extreme predicates are not recursive with non-extreme-predicate functions (and only
 2766        // with extreme predicates of the same polarity), and
 2767        // check that greatest lemmas are not recursive with non-greatest-lemma methods.
 2768        // Also, check that the constraints of newtypes/subset-types do not depend on the type itself.
 2769        // And check that const initializers are not cyclic.
 8582770        var cycleErrorHasBeenReported = new HashSet<ICallable>();
 92582771        foreach (var d in declarations) {
 38442772          if (d is TopLevelDeclWithMembers { Members: var members }) {
 203042773            foreach (var member in members) {
 51522774              if (member is ExtremePredicate) {
 02775                var fn = (ExtremePredicate)member;
 2776                // Check here for the presence of any 'ensures' clauses, which are not allowed (because we're not sure
 2777                // of their soundness)
 02778                fn.Req.ForEach(e => ExtremePredicateChecks(e.E, fn, CallingPosition.Positive));
 02779                fn.Decreases.Expressions.ForEach(e => ExtremePredicateChecks(e, fn, CallingPosition.Positive));
 02780                fn.Reads.ForEach(e => ExtremePredicateChecks(e.E, fn, CallingPosition.Positive));
 02781                if (fn.Ens.Count != 0) {
 02782                  reporter.Error(MessageSource.Resolver, fn.Ens[0].E.tok, "a {0} is not allowed to declare any ensures c
 02783                }
 02784                if (fn.Body != null) {
 02785                  ExtremePredicateChecks(fn.Body, fn, CallingPosition.Positive);
 02786                }
 51522787              } else if (member is ExtremeLemma) {
 02788                var m = (ExtremeLemma)member;
 02789                m.Req.ForEach(e => ExtremeLemmaChecks(e.E, m));
 02790                m.Ens.ForEach(e => ExtremeLemmaChecks(e.E, m));
 02791                m.Decreases.Expressions.ForEach(e => ExtremeLemmaChecks(e, m));
 2792
 02793                if (m.Body != null) {
 02794                  ExtremeLemmaChecks(m.Body, m);
 02795                }
 51522796              } else if (member is ConstantField) {
 02797                var cf = (ConstantField)member;
 02798                if (cf.EnclosingModule.CallGraph.GetSCCSize(cf) != 1) {
 02799                  var r = cf.EnclosingModule.CallGraph.GetSCCRepresentative(cf);
 02800                  if (cycleErrorHasBeenReported.Contains(r)) {
 2801                    // An error has already been reported for this cycle, so don't report another.
 2802                    // Note, the representative, "r", may itself not be a const.
 02803                  } else {
 02804                    ReportCallGraphCycleError(cf, "const definition contains a cycle");
 02805                    cycleErrorHasBeenReported.Add(r);
 02806                  }
 02807                }
 02808              }
 51522809            }
 16162810          }
 2811
 28402812          if (d is RedirectingTypeDecl dd) {
 6122813            if (d.EnclosingModuleDefinition.CallGraph.GetSCCSize(dd) != 1) {
 02814              var r = d.EnclosingModuleDefinition.CallGraph.GetSCCRepresentative(dd);
 02815              if (cycleErrorHasBeenReported.Contains(r)) {
 2816                // An error has already been reported for this cycle, so don't report another.
 2817                // Note, the representative, "r", may itself not be a const.
 02818              } else if (dd is NewtypeDecl || dd is SubsetTypeDecl) {
 02819                ReportCallGraphCycleError(dd, $"recursive constraint dependency involving a {dd.WhatKind}");
 02820                cycleErrorHasBeenReported.Add(r);
 02821              }
 02822            }
 6122823          }
 22282824        }
 8582825      }
 2826
 2827      // ---------------------------------- Pass 3 ----------------------------------
 2828      // Further checks
 2829      // ----------------------------------------------------------------------------
 2830
 17462831      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2832        // Check that type-parameter variance is respected in type definitions
 92582833        foreach (TopLevelDecl d in declarations) {
 33922834          if (d is IteratorDecl || d is ClassDecl) {
 44102835            foreach (var tp in d.TypeArgs) {
 3062836              if (tp.Variance != TypeParameter.TPVariance.Non) {
 02837                reporter.Error(MessageSource.Resolver, tp.tok, "{0} declarations only support non-variant type parameter
 02838              }
 3062839            }
 28402840          } else if (d is TypeSynonymDecl) {
 6122841            var dd = (TypeSynonymDecl)d;
 6122842            CheckVariance(dd.Rhs, dd, TypeParameter.TPVariance.Co, false);
 10642843          } else if (d is NewtypeDecl) {
 02844            var dd = (NewtypeDecl)d;
 02845            CheckVariance(dd.BaseType, dd, TypeParameter.TPVariance.Co, false);
 9042846          } else if (d is DatatypeDecl) {
 4522847            var dd = (DatatypeDecl)d;
 40022848            foreach (var ctor in dd.Ctors) {
 16122849              ctor.Formals.Iter(formal => CheckVariance(formal.Type, dd, TypeParameter.TPVariance.Co, false));
 8822850            }
 4522851          }
 22282852        }
 8582853      }
 2854
 17462855      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2856        // Check that usage of "this" is restricted before "new;" in constructor bodies,
 2857        // and that a class without any constructor only has fields with known initializers.
 2858        // Also check that static fields (which are necessarily const) have initializers.
 8582859        var cdci = new CheckDividedConstructorInit_Visitor(this);
 74222860        foreach (var cl in ModuleDefinition.AllTypesWithMembers(declarations)) {
 20682861          if (!(cl is ClassDecl)) {
 9042862            if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract) {
 2863              // non-reference types (datatype, newtype, opaque) don't have constructors that can initialize fields
 13562864              foreach (var member in cl.Members) {
 02865                if (member is ConstantField f && f.Rhs == null && !f.IsExtern(Options, out _, out _)) {
 02866                  CheckIsOkayWithoutRHS(f);
 02867                }
 02868              }
 4522869            }
 4522870            continue;
 2871          }
 14702872          if (cl is TraitDecl) {
 6122873            if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract) {
 2874              // traits never have constructors, but check for static consts
 9182875              foreach (var member in cl.Members) {
 02876                if (member is ConstantField f && f.IsStatic && f.Rhs == null && !f.IsExtern(Options, out _, out _)) {
 02877                  CheckIsOkayWithoutRHS(f);
 02878                }
 02879              }
 3062880            }
 3062881            continue;
 2882          }
 8582883          var hasConstructor = false;
 8582884          Field fieldWithoutKnownInitializer = null;
 180302885          foreach (var member in cl.Members) {
 51522886            if (member is Constructor) {
 02887              hasConstructor = true;
 02888              var constructor = (Constructor)member;
 02889              if (constructor.BodyInit != null) {
 02890                cdci.CheckInit(constructor.BodyInit);
 02891              }
 51522892            } else if (member is ConstantField && member.IsStatic) {
 02893              var f = (ConstantField)member;
 02894              if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract && f.Rhs == null && !f.IsExtern(Options, out _
 02895                CheckIsOkayWithoutRHS(f);
 02896              }
 54582897            } else if (member is Field && fieldWithoutKnownInitializer == null) {
 3062898              var f = (Field)member;
 3062899              if (f is ConstantField && ((ConstantField)f).Rhs != null) {
 2900                // fine
 3062901              } else if (!f.Type.KnownToHaveToAValue(f.IsGhost)) {
 02902                fieldWithoutKnownInitializer = f;
 02903              }
 3062904            }
 51522905          }
 17162906          if (!hasConstructor) {
 17162907            if (fieldWithoutKnownInitializer == null) {
 2908              // time to check inherited members
 25742909              foreach (var member in cl.InheritedMembers) {
 02910                if (member is Field) {
 02911                  var f = (Field)member;
 02912                  if (f is ConstantField && ((ConstantField)f).Rhs != null) {
 2913                    // fine
 02914                  } else if (!f.Type.Subst(cl.ParentFormalTypeParametersToActuals).KnownToHaveToAValue(f.IsGhost)) {
 02915                    fieldWithoutKnownInitializer = f;
 02916                    break;
 2917                  }
 02918                }
 02919              }
 8582920            }
 2921            // go through inherited members...
 8582922            if (fieldWithoutKnownInitializer != null) {
 02923              reporter.Error(MessageSource.Resolver, cl.tok, "class '{0}' with fields without known initializers, like '
 02924                cl.Name, fieldWithoutKnownInitializer.Name, fieldWithoutKnownInitializer.Type.Subst(cl.ParentFormalTypeP
 02925            }
 8582926          }
 8582927        }
 8582928      }
 2929      // Verifies that, in all compiled places, subset types in comprehensions have a compilable constraint
 8882930      new SubsetConstraintGhostChecker(this.Reporter).Traverse(declarations);
 8882931    }
 2932
 8582933    private void FillInPostConditionsAndBodiesOfPrefixLemmas(List<TopLevelDecl> declarations) {
 25742934      foreach (var com in ModuleDefinition.AllExtremeLemmas(declarations)) {
 02935        var prefixLemma = com.PrefixLemma;
 02936        if (prefixLemma == null) {
 02937          continue; // something went wrong during registration of the prefix lemma (probably a duplicated extreme lemma
 2938        }
 2939
 02940        var k = prefixLemma.Ins[0];
 02941        var focalPredicates = new HashSet<ExtremePredicate>();
 02942        if (com is GreatestLemma) {
 2943          // compute the postconditions of the prefix lemma
 02944          Contract.Assume(prefixLemma.Ens.Count == 0); // these are not supposed to have been filled in before
 02945          foreach (var p in com.Ens) {
 02946            var coConclusions = new HashSet<Expression>();
 02947            CollectFriendlyCallsInExtremeLemmaSpecification(p.E, true, coConclusions, true, com);
 02948            var subst = new ExtremeLemmaSpecificationSubstituter(coConclusions, new IdentifierExpr(k.tok, k.Name),
 02949              this.reporter, true);
 02950            var post = subst.CloneExpr(p.E);
 02951            prefixLemma.Ens.Add(new AttributedExpression(post));
 02952            foreach (var e in coConclusions) {
 02953              var fce = e as FunctionCallExpr;
 02954              if (fce != null) {
 2955                // the other possibility is that "e" is a BinaryExpr
 02956                GreatestPredicate predicate = (GreatestPredicate)fce.Function;
 02957                focalPredicates.Add(predicate);
 2958                // For every focal predicate P in S, add to S all greatest predicates in the same strongly connected
 2959                // component (in the call graph) as P
 02960                foreach (var node in predicate.EnclosingClass.EnclosingModuleDefinition.CallGraph.GetSCC(
 02961                           predicate)) {
 02962                  if (node is GreatestPredicate) {
 02963                    focalPredicates.Add((GreatestPredicate)node);
 02964                  }
 02965                }
 02966              }
 02967            }
 02968          }
 02969        } else {
 2970          // compute the preconditions of the prefix lemma
 02971          Contract.Assume(prefixLemma.Req.Count == 0); // these are not supposed to have been filled in before
 02972          foreach (var p in com.Req) {
 02973            var antecedents = new HashSet<Expression>();
 02974            CollectFriendlyCallsInExtremeLemmaSpecification(p.E, true, antecedents, false, com);
 02975            var subst = new ExtremeLemmaSpecificationSubstituter(antecedents, new IdentifierExpr(k.tok, k.Name),
 02976              this.reporter, false);
 02977            var pre = subst.CloneExpr(p.E);
 02978            prefixLemma.Req.Add(new AttributedExpression(pre, p.Label, null));
 02979            foreach (var e in antecedents) {
 02980              var fce = (FunctionCallExpr)e; // we expect "antecedents" to contain only FunctionCallExpr's
 02981              LeastPredicate predicate = (LeastPredicate)fce.Function;
 02982              focalPredicates.Add(predicate);
 2983              // For every focal predicate P in S, add to S all least predicates in the same strongly connected
 2984              // component (in the call graph) as P
 02985              foreach (var node in predicate.EnclosingClass.EnclosingModuleDefinition.CallGraph.GetSCC(predicate)) {
 02986                if (node is LeastPredicate) {
 02987                  focalPredicates.Add((LeastPredicate)node);
 02988                }
 02989              }
 02990            }
 02991          }
 02992        }
 2993
 02994        reporter.Info(MessageSource.Resolver, com.tok,
 02995          focalPredicates.Count == 0
 02996            ? $"{com.PrefixLemma.Name} has no focal predicates"
 02997            : $"{com.PrefixLemma.Name} with focal predicate{Util.Plural(focalPredicates.Count)} {Util.Comma(focalPredica
 2998        // Compute the statement body of the prefix lemma
 02999        Contract.Assume(prefixLemma.Body == null); // this is not supposed to have been filled in before
 03000        if (com.Body != null) {
 03001          var kMinusOne = new BinaryExpr(com.tok, BinaryExpr.Opcode.Sub, new IdentifierExpr(k.tok, k.Name),
 03002            new LiteralExpr(com.tok, 1));
 03003          var subst = new ExtremeLemmaBodyCloner(com, kMinusOne, focalPredicates, this.reporter);
 03004          var mainBody = subst.CloneBlockStmt(com.Body);
 3005          Expression kk;
 3006          Statement els;
 03007          if (k.Type.IsBigOrdinalType) {
 03008            kk = new MemberSelectExpr(k.tok, new IdentifierExpr(k.tok, k.Name), "Offset");
 3009            // As an "else" branch, we add recursive calls for the limit case.  When automatic induction is on,
 3010            // this get handled automatically, but we still want it in the case when automatic induction has been
 3011            // turned off.
 3012            //     forall k', params | k' < _k && Precondition {
 3013            //       pp(k', params);
 3014            //     }
 03015            Contract.Assume(builtIns.ORDINAL_Offset != null); // should have been filled in earlier
 03016            var kId = new IdentifierExpr(com.tok, k);
 03017            var kprimeVar = new BoundVar(com.tok, "_k'", Type.BigOrdinal);
 03018            var kprime = new IdentifierExpr(com.tok, kprimeVar);
 03019            var smaller = Expression.CreateLess(kprime, kId);
 3020
 03021            var bvs = new List<BoundVar>(); // the following loop populates bvs with k', params
 03022            var substMap = new Dictionary<IVariable, Expression>();
 03023            foreach (var inFormal in prefixLemma.Ins) {
 03024              if (inFormal == k) {
 03025                bvs.Add(kprimeVar);
 03026                substMap.Add(k, kprime);
 03027              } else {
 03028                var bv = new BoundVar(inFormal.tok, inFormal.Name, inFormal.Type);
 03029                bvs.Add(bv);
 03030                substMap.Add(inFormal, new IdentifierExpr(com.tok, bv));
 03031              }
 03032            }
 3033
 03034            Translator.RecursiveCallParameters(com.tok, prefixLemma, prefixLemma.TypeArgs, prefixLemma.Ins, null,
 03035              substMap, out var recursiveCallReceiver, out var recursiveCallArgs);
 03036            var methodSel = new MemberSelectExpr(com.tok, recursiveCallReceiver, prefixLemma.Name);
 03037            methodSel.Member = prefixLemma; // resolve here
 03038            methodSel.TypeApplication_AtEnclosingClass =
 03039              prefixLemma.EnclosingClass.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp.tok, tp));
 03040            methodSel.TypeApplication_JustMember =
 03041              prefixLemma.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp.tok, tp));
 03042            methodSel.Type = new InferredTypeProxy();
 03043            var recursiveCall = new CallStmt(com.RangeToken, new List<Expression>(), methodSel,
 03044              recursiveCallArgs.ConvertAll(e => new ActualBinding(null, e)));
 03045            recursiveCall.IsGhost = prefixLemma.IsGhost; // resolve here
 3046
 03047            var range = smaller; // The range will be strengthened later with the call's precondition, substituted
 3048            // appropriately (which can only be done once the precondition has been resolved).
 03049            var attrs = new Attributes("_autorequires", new List<Expression>(), null);
 3050#if VERIFY_CORRECTNESS_OF_TRANSLATION_FORALL_STATEMENT_RANGE
 3051              // don't add the :_trustWellformed attribute
 3052#else
 03053            attrs = new Attributes("_trustWellformed", new List<Expression>(), attrs);
 3054#endif
 03055            attrs = new Attributes("auto_generated", new List<Expression>(), attrs);
 03056            var forallBody = new BlockStmt(mainBody.RangeToken, new List<Statement>() { recursiveCall });
 03057            var forallStmt = new ForallStmt(mainBody.RangeToken, bvs, attrs, range,
 03058              new List<AttributedExpression>(), forallBody);
 03059            els = new BlockStmt(mainBody.RangeToken, new List<Statement>() { forallStmt });
 03060          } else {
 03061            kk = new IdentifierExpr(k.tok, k.Name);
 03062            els = null;
 03063          }
 3064
 03065          var kPositive = new BinaryExpr(com.tok, BinaryExpr.Opcode.Lt, new LiteralExpr(com.tok, 0), kk);
 03066          var condBody = new IfStmt(mainBody.RangeToken, false, kPositive, mainBody, els);
 03067          prefixLemma.Body = new BlockStmt(mainBody.RangeToken, new List<Statement>() { condBody });
 03068        }
 3069
 3070        // The prefix lemma now has all its components, so it's finally time we resolve it
 03071        currentClass = (TopLevelDeclWithMembers)prefixLemma.EnclosingClass;
 03072        allTypeParameters.PushMarker();
 03073        ResolveTypeParameters(currentClass.TypeArgs, false, currentClass);
 03074        ResolveTypeParameters(prefixLemma.TypeArgs, false, prefixLemma);
 03075        prefixLemma.Resolve(this);
 03076        allTypeParameters.PopMarker();
 03077        currentClass = null;
 03078        new CheckTypeInferenceVisitor(this).VisitMethod(prefixLemma);
 03079        CallGraphBuilder.VisitMethod(prefixLemma, reporter);
 03080        new BoundsDiscoveryVisitor(reporter).VisitMethod(prefixLemma);
 03081      }
 8583082    }
 3083
 03084    private void CheckIsOkayWithoutRHS(ConstantField f) {
 03085      if (f.IsGhost && !f.Type.IsNonempty) {
 03086        reporter.Error(MessageSource.Resolver, f.tok,
 03087          "{0}ghost const field '{1}' of type '{2}' (which may be empty) must give a defining value",
 03088          f.IsStatic ? "static " : "", f.Name, f.Type);
 03089      } else if (!f.IsGhost && !f.Type.HasCompilableValue) {
 03090        reporter.Error(MessageSource.Resolver, f.tok,
 03091          "{0}non-ghost const field '{1}' of type '{2}' (which does not have a default compiled value) must give a defin
 03092          f.IsStatic ? "static " : "", f.Name, f.Type);
 03093      }
 03094    }
 3095
 16163096    private void ResolveClassMembers_Pass1(TopLevelDeclWithMembers cl) {
 203043097      foreach (var member in cl.Members) {
 51523098        var prevErrCnt = reporter.Count(ErrorLevel.Error);
 103043099        if (prevErrCnt == reporter.Count(ErrorLevel.Error)) {
 99983100          if (member is Method method) {
 48463101            CheckForUnnecessaryEqualitySupportDeclarations(method, method.TypeArgs);
 48463102            CheckParameterDefaultValuesAreCompilable(method.Ins, method);
 96923103            if (method.Body != null) {
 48463104              ComputeGhostInterest(method.Body, method.IsGhost, method.IsLemmaLike ? "a " + method.WhatKind : null, meth
 48463105              CheckExpression(method.Body, this, method);
 48463106              new TailRecursion(reporter).DetermineTailRecursion(method);
 48463107            }
 3108
 51523109          } else if (member is Function function) {
 03110            CheckForUnnecessaryEqualitySupportDeclarations(function, function.TypeArgs);
 03111            CheckParameterDefaultValuesAreCompilable(function.Formals, function);
 03112            if (function.ByMethodBody == null) {
 03113              if (!function.IsGhost && function.Body != null) {
 03114                ExpressionTester.CheckIsCompilable(Options, this, function.Body, function);
 03115              }
 03116              if (function.Body != null) {
 03117                new TailRecursion(reporter).DetermineTailRecursion(function);
 03118              }
 03119            } else {
 03120              var m = function.ByMethodDecl;
 03121              if (m != null) {
 03122                Contract.Assert(!m.IsGhost);
 03123                ComputeGhostInterest(m.Body, false, null, m);
 03124                CheckExpression(m.Body, this, m);
 03125                new TailRecursion(reporter).DetermineTailRecursion(m);
 03126              } else {
 3127                // m should not be null, unless an error has been reported
 3128                // (e.g. function-by-method and method with the same name)
 03129                Contract.Assert(reporter.ErrorCount > 0);
 03130              }
 03131            }
 3132
 3063133          } else if (member is ConstantField field && field.Rhs != null && !field.IsGhost) {
 03134            ExpressionTester.CheckIsCompilable(Options, this, field.Rhs, field);
 03135          }
 3136
 99983137          if (prevErrCnt == reporter.Count(ErrorLevel.Error) && member is ICodeContext) {
 96243138            member.SubExpressions.Iter(e => CheckExpression(e, this, (ICodeContext)member));
 48463139          }
 51523140        }
 51523141      }
 16163142    }
 3143
 48463144    void CheckForUnnecessaryEqualitySupportDeclarations(MemberDecl member, List<TypeParameter> typeParameters) {
 48463145      if (member.IsGhost) {
 03146        foreach (var p in typeParameters.Where(p => p.SupportsEquality)) {
 03147          reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, p.tok,
 03148            $"type parameter {p.Name} of ghost {member.WhatKind} {member.Name} is declared (==), which is unnecessary be
 03149        }
 03150      }
 48463151    }
 3152
 3153    /// <summary>
 3154    /// Check that default-value expressions are compilable, for non-ghost formals.
 3155    /// </summary>
 57283156    void CheckParameterDefaultValuesAreCompilable(List<Formal> formals, ICodeContext codeContext) {
 3157      Contract.Requires(formals != null);
 3158
 280183159      foreach (var formal in formals.Where(f => f.DefaultValue != null)) {
 03160        if ((!codeContext.IsGhost || codeContext is DatatypeDecl) && !formal.IsGhost) {
 03161          ExpressionTester.CheckIsCompilable(Options, this, formal.DefaultValue, codeContext);
 03162        }
 03163        CheckExpression(formal.DefaultValue, this, codeContext);
 03164      }
 57283165    }
 3166
 03167    void ReportCallGraphCycleError(ICallable start, string msg) {
 3168      Contract.Requires(start != null);
 3169      Contract.Requires(msg != null);
 03170      var scc = start.EnclosingModule.CallGraph.GetSCC(start);
 03171      scc.Reverse();
 03172      var startIndex = scc.IndexOf(start);
 03173      Contract.Assert(0 <= startIndex);
 03174      scc = Util.Concat(scc.GetRange(startIndex, scc.Count - startIndex), scc.GetRange(0, startIndex));
 03175      ReportCycleError(scc, c => c.Tok, c => c.NameRelativeToModule, msg);
 03176    }
 3177
 03178    void ReportCycleError<X>(List<X> cycle, Func<X, IToken> toTok, Func<X, string> toString, string msg) {
 3179      Contract.Requires(cycle != null);
 3180      Contract.Requires(cycle.Count != 0);
 3181      Contract.Requires(toTok != null);
 3182      Contract.Requires(toString != null);
 3183      Contract.Requires(msg != null);
 3184
 03185      var start = cycle[0];
 03186      var cy = Util.Comma(" -> ", cycle, toString);
 03187      reporter.Error(MessageSource.Resolver, toTok(start), $"{msg}: {cy} -> {toString(start)}");
 03188    }
 3189
 3190    /// <summary>
 3191    /// Returns the largest value that can be stored in bitvector type "t".
 3192    /// </summary>
 03193    public static BigInteger MaxBV(Type t) {
 3194      Contract.Requires(t != null);
 3195      Contract.Requires(t.IsBitVectorType);
 03196      return MaxBV(t.AsBitVectorType.Width);
 03197    }
 3198
 3199    /// <summary>
 3200    /// Returns the largest value that can be stored in bitvector type of "bits" width.
 3201    /// </summary>
 03202    public static BigInteger MaxBV(int bits) {
 3203      Contract.Requires(0 <= bits);
 03204      return BigInteger.Pow(new BigInteger(2), bits) - BigInteger.One;
 03205    }
 3206
 03207    private void FigureOutNativeType(NewtypeDecl dd) {
 3208      Contract.Requires(dd != null);
 3209
 3210      // Look at the :nativeType attribute, if any
 3211      bool mustUseNativeType;
 03212      List<NativeType> nativeTypeChoices = null;  // null means "no preference"
 03213      var args = Attributes.FindExpressions(dd.Attributes, "nativeType");
 03214      if (args != null && !dd.BaseType.IsNumericBased(Type.NumericPersuasion.Int)) {
 03215        reporter.Error(MessageSource.Resolver, dd, ":nativeType can only be used on integral types");
 03216        return;
 03217      } else if (args == null) {
 3218        // There was no :nativeType attribute
 03219        mustUseNativeType = false;
 03220      } else if (args.Count == 0) {
 03221        mustUseNativeType = true;
 03222      } else {
 03223        var arg0Lit = args[0] as LiteralExpr;
 03224        if (arg0Lit != null && arg0Lit.Value is bool) {
 03225          if (!(bool)arg0Lit.Value) {
 3226            // {:nativeType false} says "don't use native type", so our work here is done
 03227            return;
 3228          }
 03229          mustUseNativeType = true;
 03230        } else {
 03231          mustUseNativeType = true;
 03232          nativeTypeChoices = new List<NativeType>();
 03233          foreach (var arg in args) {
 03234            if (arg is LiteralExpr lit && lit.Value is string s) {
 3235              // Get the NativeType for "s"
 03236              foreach (var nativeT in NativeTypes) {
 03237                if (nativeT.Name == s) {
 03238                  nativeTypeChoices.Add(nativeT);
 03239                  goto FoundNativeType;
 3240                }
 03241              }
 03242              reporter.Error(MessageSource.Resolver, dd, ":nativeType '{0}' not known", s);
 03243              return;
 03244            FoundNativeType:;
 03245            } else {
 03246              reporter.Error(MessageSource.Resolver, arg, "unexpected :nativeType argument");
 03247              return;
 3248            }
 03249          }
 03250        }
 03251      }
 3252
 3253      // Figure out the variable and constraint.  Usually, these would be just .Var and .Constraint, but
 3254      // in the case .Var is null, these can be computed from the .BaseType recursively.
 03255      var ddVar = dd.Var;
 03256      var ddConstraint = dd.Constraint;
 03257      for (var ddWhereConstraintsAre = dd; ddVar == null;) {
 03258        ddWhereConstraintsAre = ddWhereConstraintsAre.BaseType.AsNewtype;
 03259        if (ddWhereConstraintsAre == null) {
 03260          break;
 3261        }
 03262        ddVar = ddWhereConstraintsAre.Var;
 03263        ddConstraint = ddWhereConstraintsAre.Constraint;
 03264      }
 3265      List<ComprehensionExpr.BoundedPool> bounds;
 03266      if (ddVar == null) {
 3267        // There are no bounds at all
 03268        bounds = new List<ComprehensionExpr.BoundedPool>();
 03269      } else {
 03270        bounds = DiscoverAllBounds_SingleVar(ddVar, ddConstraint);
 03271      }
 3272
 3273      // Returns null if the argument is a constrained newtype (recursively)
 3274      // Returns the transitive base type if the argument is recusively unconstrained
 03275      Type AsUnconstrainedType(Type t) {
 03276        while (true) {
 03277          if (t.AsNewtype == null) {
 03278            return t;
 3279          }
 3280
 03281          if (t.AsNewtype.Constraint != null) {
 03282            return null;
 3283          }
 3284
 03285          t = t.AsNewtype.BaseType;
 03286        }
 03287      }
 3288
 3289      // Find which among the allowable native types can hold "dd". Give an
 3290      // error for any user-specified native type that's not big enough.
 03291      var bigEnoughNativeTypes = new List<NativeType>();
 3292      // But first, define a local, recursive function GetConst/GetAnyConst:
 3293      // These fold any constant computations, including symbolic constants,
 3294      // returning null if folding is not possible. If an operation is undefined
 3295      // (divide by zero, conversion out of range, etc.), then null is returned.
 03296      Func<Expression, BigInteger?> GetConst = null;
 03297      Func<Expression, Stack<ConstantField>, Object> GetAnyConst = null;
 03298      GetAnyConst = (Expression e, Stack<ConstantField> consts) => {
 03299        if (e is LiteralExpr l) {
 03300          return l.Value;
 03301        } else if (e is UnaryOpExpr un) {
 03302          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot && GetAnyConst(un.E, consts) is bool b) {
 03303            return !b;
 03304          }
 03305          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BVNot && GetAnyConst(un.E, consts) is BigInteger i) {
 03306            return ((BigInteger.One << un.Type.AsBitVectorType.Width) - 1) ^ i;
 03307          }
 03308          // TODO: This only handles strings; generalize to other collections?
 03309          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.SeqLength && GetAnyConst(un.E, consts) is string ss) {
 03310            return (BigInteger)(ss.Length);
 03311          }
 03312        } else if (e is MemberSelectExpr m) {
 03313          if (m.Member is ConstantField c && c.IsStatic && c.Rhs != null) {
 03314            // This aspect of type resolution happens before the check for cyclic references
 03315            // so we have to do a check here as well. If cyclic, null is silently returned,
 03316            // counting on the later error message to alert the user.
 03317            if (consts.Contains(c)) { return null; }
 03318            consts.Push(c);
 03319            Object o = GetAnyConst(c.Rhs, consts);
 03320            consts.Pop();
 03321            return o;
 03322          } else if (m.Member is SpecialField sf) {
 03323            string nm = sf.Name;
 03324            if (nm == "Floor") {
 03325              Object ee = GetAnyConst(m.Obj, consts);
 03326              if (ee != null && m.Obj.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03327                ((BaseTypes.BigDec)ee).FloorCeiling(out var f, out _);
 03328                return f;
 03329              }
 03330            }
 03331          }
 03332        } else if (e is BinaryExpr bin) {
 03333          Object e0 = GetAnyConst(bin.E0, consts);
 03334          Object e1 = GetAnyConst(bin.E1, consts);
 03335          bool isBool = bin.E0.Type == Type.Bool && bin.E1.Type == Type.Bool;
 03336          bool shortCircuit = isBool && (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.And
 03337                                         || bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Or
 03338                                         || bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Imp);
 03339
 03340          if (e0 == null || (!shortCircuit && e1 == null)) { return null; }
 03341          bool isAnyReal = bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Real)
 03342                        && bin.E1.Type.IsNumericBased(Type.NumericPersuasion.Real);
 03343          bool isAnyInt = bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Int)
 03344                       && bin.E1.Type.IsNumericBased(Type.NumericPersuasion.Int);
 03345          bool isReal = bin.Type.IsRealType;
 03346          bool isInt = bin.Type.IsIntegerType;
 03347          bool isBV = bin.E0.Type.IsBitVectorType;
 03348          int width = isBV ? bin.E0.Type.AsBitVectorType.Width : 0;
 03349          bool isString = e0 is string && e1 is string;
 03350          switch (bin.ResolvedOp) {
 03351            case BinaryExpr.ResolvedOpcode.Add:
 03352              if (isInt) {
 03353                return (BigInteger)e0 + (BigInteger)e1;
 03354              }
 03355
 03356              if (isBV) {
 03357                return ((BigInteger)e0 + (BigInteger)e1) & MaxBV(bin.Type);
 03358              }
 03359
 03360              if (isReal) {
 03361                return (BaseTypes.BigDec)e0 + (BaseTypes.BigDec)e1;
 03362              }
 03363
 03364              break;
 03365            case BinaryExpr.ResolvedOpcode.Concat:
 03366              if (isString) {
 03367                return (string)e0 + (string)e1;
 03368              }
 03369
 03370              break;
 03371            case BinaryExpr.ResolvedOpcode.Sub:
 03372              if (isInt) {
 03373                return (BigInteger)e0 - (BigInteger)e1;
 03374              }
 03375
 03376              if (isBV) {
 03377                return ((BigInteger)e0 - (BigInteger)e1) & MaxBV(bin.Type);
 03378              }
 03379
 03380              if (isReal) {
 03381                return (BaseTypes.BigDec)e0 - (BaseTypes.BigDec)e1;
 03382              }
 03383              // Allow a special case: If the result type is a newtype that is integer-based (i.e., isInt && !isInteger)
 03384              // then we generally do not fold the operations, because we do not determine whether the
 03385              // result of the operation satisfies the new type constraint. However, on the occasion that
 03386              // a newtype aliases int without a constraint, it occurs that a value of the newtype is initialized
 03387              // with a negative value, which is represented as "0 - N", that is, it comes to this case. It
 03388              // is a nuisance not to constant-fold the result, as not doing so can alter the determination
 03389              // of the representation type.
 03390              if (isAnyInt && AsUnconstrainedType(bin.Type) != null) {
 03391                return ((BigInteger)e0) - ((BigInteger)e1);
 03392              }
 03393              break;
 03394            case BinaryExpr.ResolvedOpcode.Mul:
 03395              if (isInt) {
 03396                return (BigInteger)e0 * (BigInteger)e1;
 03397              }
 03398
 03399              if (isBV) {
 03400                return ((BigInteger)e0 * (BigInteger)e1) & MaxBV(bin.Type);
 03401              }
 03402
 03403              if (isReal) {
 03404                return (BaseTypes.BigDec)e0 * (BaseTypes.BigDec)e1;
 03405              }
 03406
 03407              break;
 03408            case BinaryExpr.ResolvedOpcode.BitwiseAnd:
 03409              Contract.Assert(isBV);
 03410              return (BigInteger)e0 & (BigInteger)e1;
 03411            case BinaryExpr.ResolvedOpcode.BitwiseOr:
 03412              Contract.Assert(isBV);
 03413              return (BigInteger)e0 | (BigInteger)e1;
 03414            case BinaryExpr.ResolvedOpcode.BitwiseXor:
 03415              Contract.Assert(isBV);
 03416              return (BigInteger)e0 ^ (BigInteger)e1;
 03417            case BinaryExpr.ResolvedOpcode.Div:
 03418              if (isInt) {
 03419                if ((BigInteger)e1 == 0) {
 03420                  return null; // Divide by zero
 03421                } else {
 03422                  BigInteger a0 = (BigInteger)e0;
 03423                  BigInteger a1 = (BigInteger)e1;
 03424                  BigInteger d = a0 / a1;
 03425                  return a0 >= 0 || a0 == d * a1 ? d : a1 > 0 ? d - 1 : d + 1;
 03426                }
 03427              }
 03428              if (isBV) {
 03429                if ((BigInteger)e1 == 0) {
 03430                  return null; // Divide by zero
 03431                } else {
 03432                  return ((BigInteger)e0) / ((BigInteger)e1);
 03433                }
 03434              }
 03435              if (isReal) {
 03436                if ((BaseTypes.BigDec)e1 == BaseTypes.BigDec.ZERO) {
 03437                  return null; // Divide by zero
 03438                } else {
 03439                  // BigDec does not have divide and is not a representation of rationals, so we don't do constant foldi
 03440                  return null;
 03441                }
 03442              }
 03443
 03444              break;
 03445            case BinaryExpr.ResolvedOpcode.Mod:
 03446              if (isInt) {
 03447                if ((BigInteger)e1 == 0) {
 03448                  return null; // Mod by zero
 03449                } else {
 03450                  BigInteger a = BigInteger.Abs((BigInteger)e1);
 03451                  BigInteger d = (BigInteger)e0 % a;
 03452                  return (BigInteger)e0 >= 0 ? d : d + a;
 03453                }
 03454              }
 03455              if (isBV) {
 03456                if ((BigInteger)e1 == 0) {
 03457                  return null; // Mod by zero
 03458                } else {
 03459                  return (BigInteger)e0 % (BigInteger)e1;
 03460                }
 03461              }
 03462              break;
 03463            case BinaryExpr.ResolvedOpcode.LeftShift: {
 03464                if ((BigInteger)e1 < 0) {
 03465                  return null; // Negative shift
 03466                }
 03467                if ((BigInteger)e1 > bin.Type.AsBitVectorType.Width) {
 03468                  return null; // Shift is too large
 03469                }
 03470                return ((BigInteger)e0 << (int)(BigInteger)e1) & MaxBV(bin.E0.Type);
 03471              }
 03472            case BinaryExpr.ResolvedOpcode.RightShift: {
 03473                if ((BigInteger)e1 < 0) {
 03474                  return null; // Negative shift
 03475                }
 03476                if ((BigInteger)e1 > bin.Type.AsBitVectorType.Width) {
 03477                  return null; // Shift too large
 03478                }
 03479                return (BigInteger)e0 >> (int)(BigInteger)e1;
 03480              }
 03481            case BinaryExpr.ResolvedOpcode.And: {
 03482                if ((bool)e0 && e1 == null) {
 03483                  return null;
 03484                }
 03485
 03486                return (bool)e0 && (bool)e1;
 03487              }
 03488            case BinaryExpr.ResolvedOpcode.Or: {
 03489                if (!(bool)e0 && e1 == null) {
 03490                  return null;
 03491                }
 03492
 03493                return (bool)e0 || (bool)e1;
 03494              }
 03495            case BinaryExpr.ResolvedOpcode.Imp: { // ==> and <==
 03496                if ((bool)e0 && e1 == null) {
 03497                  return null;
 03498                }
 03499
 03500                return !(bool)e0 || (bool)e1;
 03501              }
 03502            case BinaryExpr.ResolvedOpcode.Iff: return (bool)e0 == (bool)e1; // <==>
 03503            case BinaryExpr.ResolvedOpcode.Gt:
 03504              if (isAnyInt) {
 03505                return (BigInteger)e0 > (BigInteger)e1;
 03506              }
 03507
 03508              if (isBV) {
 03509                return (BigInteger)e0 > (BigInteger)e1;
 03510              }
 03511
 03512              if (isAnyReal) {
 03513                return (BaseTypes.BigDec)e0 > (BaseTypes.BigDec)e1;
 03514              }
 03515
 03516              break;
 03517            case BinaryExpr.ResolvedOpcode.GtChar:
 03518              if (bin.E0.Type.IsCharType) {
 03519                return ((string)e0)[0] > ((string)e1)[0];
 03520              }
 03521
 03522              break;
 03523            case BinaryExpr.ResolvedOpcode.Ge:
 03524              if (isAnyInt) {
 03525                return (BigInteger)e0 >= (BigInteger)e1;
 03526              }
 03527
 03528              if (isBV) {
 03529                return (BigInteger)e0 >= (BigInteger)e1;
 03530              }
 03531
 03532              if (isAnyReal) {
 03533                return (BaseTypes.BigDec)e0 >= (BaseTypes.BigDec)e1;
 03534              }
 03535
 03536              break;
 03537            case BinaryExpr.ResolvedOpcode.GeChar:
 03538              if (bin.E0.Type.IsCharType) {
 03539                return ((string)e0)[0] >= ((string)e1)[0];
 03540              }
 03541
 03542              break;
 03543            case BinaryExpr.ResolvedOpcode.Lt:
 03544              if (isAnyInt) {
 03545                return (BigInteger)e0 < (BigInteger)e1;
 03546              }
 03547
 03548              if (isBV) {
 03549                return (BigInteger)e0 < (BigInteger)e1;
 03550              }
 03551
 03552              if (isAnyReal) {
 03553                return (BaseTypes.BigDec)e0 < (BaseTypes.BigDec)e1;
 03554              }
 03555
 03556              break;
 03557            case BinaryExpr.ResolvedOpcode.LtChar:
 03558              if (bin.E0.Type.IsCharType) {
 03559                return ((string)e0)[0] < ((string)e1)[0];
 03560              }
 03561
 03562              break;
 03563            case BinaryExpr.ResolvedOpcode.ProperPrefix:
 03564              if (isString) {
 03565                return ((string)e1).StartsWith((string)e0) && !((string)e1).Equals((string)e0);
 03566              }
 03567
 03568              break;
 03569            case BinaryExpr.ResolvedOpcode.Le:
 03570              if (isAnyInt) {
 03571                return (BigInteger)e0 <= (BigInteger)e1;
 03572              }
 03573
 03574              if (isBV) {
 03575                return (BigInteger)e0 <= (BigInteger)e1;
 03576              }
 03577
 03578              if (isAnyReal) {
 03579                return (BaseTypes.BigDec)e0 <= (BaseTypes.BigDec)e1;
 03580              }
 03581
 03582              break;
 03583            case BinaryExpr.ResolvedOpcode.LeChar:
 03584              if (bin.E0.Type.IsCharType) {
 03585                return ((string)e0)[0] <= ((string)e1)[0];
 03586              }
 03587
 03588              break;
 03589            case BinaryExpr.ResolvedOpcode.Prefix:
 03590              if (isString) {
 03591                return ((string)e1).StartsWith((string)e0);
 03592              }
 03593
 03594              break;
 03595            case BinaryExpr.ResolvedOpcode.EqCommon: {
 03596                if (isBool) {
 03597                  return (bool)e0 == (bool)e1;
 03598                } else if (isAnyInt || isBV) {
 03599                  return (BigInteger)e0 == (BigInteger)e1;
 03600                } else if (isAnyReal) {
 03601                  return (BaseTypes.BigDec)e0 == (BaseTypes.BigDec)e1;
 03602                } else if (bin.E0.Type.IsCharType) {
 03603                  return ((string)e0)[0] == ((string)e1)[0];
 03604                }
 03605                break;
 03606              }
 03607            case BinaryExpr.ResolvedOpcode.SeqEq:
 03608              if (isString) {
 03609                return (string)e0 == (string)e1;
 03610              }
 03611              break;
 03612            case BinaryExpr.ResolvedOpcode.SeqNeq:
 03613              if (isString) {
 03614                return (string)e0 != (string)e1;
 03615              }
 03616              break;
 03617            case BinaryExpr.ResolvedOpcode.NeqCommon: {
 03618                if (isBool) {
 03619                  return (bool)e0 != (bool)e1;
 03620                } else if (isAnyInt || isBV) {
 03621                  return (BigInteger)e0 != (BigInteger)e1;
 03622                } else if (isAnyReal) {
 03623                  return (BaseTypes.BigDec)e0 != (BaseTypes.BigDec)e1;
 03624                } else if (bin.E0.Type.IsCharType) {
 03625                  return ((string)e0)[0] != ((string)e1)[0];
 03626                } else if (isString) {
 03627                  return (string)e0 != (string)e1;
 03628                }
 03629                break;
 03630              }
 03631          }
 03632        } else if (e is ConversionExpr ce) {
 03633          object o = GetAnyConst(ce.E, consts);
 03634          if (o == null || ce.E.Type == ce.Type) {
 03635            return o;
 03636          }
 03637
 03638          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03639                ce.Type.IsBitVectorType) {
 03640            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03641            if (ff < 0 || ff > MaxBV(ce.Type)) {
 03642              return null; // Out of range
 03643            }
 03644            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03645              return null; // Out of range
 03646            }
 03647            return ff;
 03648          }
 03649
 03650          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03651                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03652            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03653            if (AsUnconstrainedType(ce.Type) == null) {
 03654              return null;
 03655            }
 03656
 03657            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03658              return null; // Argument not an integer
 03659            }
 03660            return ff;
 03661          }
 03662
 03663          if (ce.E.Type.IsBitVectorType &&
 03664                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03665            if (AsUnconstrainedType(ce.Type) == null) {
 03666              return null;
 03667            }
 03668
 03669            return o;
 03670          }
 03671
 03672          if (ce.E.Type.IsBitVectorType &&
 03673                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03674            if (AsUnconstrainedType(ce.Type) == null) {
 03675              return null;
 03676            }
 03677
 03678            return BaseTypes.BigDec.FromBigInt((BigInteger)o);
 03679          }
 03680
 03681          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03682                ce.Type.IsBitVectorType) {
 03683            BigInteger b = (BigInteger)o;
 03684            if (b < 0 || b > MaxBV(ce.Type)) {
 03685              return null; // Argument out of range
 03686            }
 03687            return o;
 03688          }
 03689
 03690          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03691                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03692            // This case includes int-based newtypes to int-based new types
 03693            if (AsUnconstrainedType(ce.Type) == null) {
 03694              return null;
 03695            }
 03696
 03697            return o;
 03698          }
 03699
 03700          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03701                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03702            // This case includes real-based newtypes to real-based new types
 03703            if (AsUnconstrainedType(ce.Type) == null) {
 03704              return null;
 03705            }
 03706
 03707            return o;
 03708          }
 03709
 03710          if (ce.E.Type.IsBitVectorType && ce.Type.IsBitVectorType) {
 03711            BigInteger b = (BigInteger)o;
 03712            if (b < 0 || b > MaxBV(ce.Type)) {
 03713              return null; // Argument out of range
 03714            }
 03715            return o;
 03716          }
 03717
 03718          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03719                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03720            if (AsUnconstrainedType(ce.Type) == null) {
 03721              return null;
 03722            }
 03723
 03724            return BaseTypes.BigDec.FromBigInt((BigInteger)o);
 03725          }
 03726
 03727          if (ce.E.Type.IsCharType && ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03728            char c = ((String)o)[0];
 03729            if (AsUnconstrainedType(ce.Type) == null) {
 03730              return null;
 03731            }
 03732
 03733            return new BigInteger(((string)o)[0]);
 03734          }
 03735
 03736          if (ce.E.Type.IsCharType && ce.Type.IsBitVectorType) {
 03737            char c = ((String)o)[0];
 03738            if ((int)c > MaxBV(ce.Type)) {
 03739              return null; // Argument out of range
 03740            }
 03741            return new BigInteger(((string)o)[0]);
 03742          }
 03743
 03744          if ((ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) || ce.E.Type.IsBitVectorType) &&
 03745                ce.Type.IsCharType) {
 03746            BigInteger b = (BigInteger)o;
 03747            if (b < BigInteger.Zero || b > new BigInteger(65535)) {
 03748              return null; // Argument out of range
 03749            }
 03750            return ((char)(int)b).ToString();
 03751          }
 03752
 03753          if (ce.E.Type.IsCharType &&
 03754              ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03755            if (AsUnconstrainedType(ce.Type) == null) {
 03756              return null;
 03757            }
 03758
 03759            return BaseTypes.BigDec.FromInt(((string)o)[0]);
 03760          }
 03761
 03762          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03763                ce.Type.IsCharType) {
 03764            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03765            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03766              return null; // Argument not an integer
 03767            }
 03768            if (ff < BigInteger.Zero || ff > new BigInteger(65535)) {
 03769              return null; // Argument out of range
 03770            }
 03771            return ((char)(int)ff).ToString();
 03772          }
 03773
 03774        } else if (e is SeqSelectExpr sse) {
 03775          var b = GetAnyConst(sse.Seq, consts) as string;
 03776          BigInteger index = (BigInteger)GetAnyConst(sse.E0, consts);
 03777          if (b == null) {
 03778            return null;
 03779          }
 03780
 03781          if (index < 0 || index >= b.Length || index > Int32.MaxValue) {
 03782            return null; // Index out of range
 03783          }
 03784          return b[(int)index].ToString();
 03785        } else if (e is ITEExpr ite) {
 03786          Object b = GetAnyConst(ite.Test, consts);
 03787          if (b == null) {
 03788            return null;
 03789          }
 03790
 03791          return ((bool)b) ? GetAnyConst(ite.Thn, consts) : GetAnyConst(ite.Els, consts);
 03792        } else if (e is ConcreteSyntaxExpression n) {
 03793          return GetAnyConst(n.ResolvedExpression, consts);
 03794        } else {
 03795          return null;
 03796        }
 03797        return null;
 03798      };
 03799      GetConst = (Expression e) => {
 03800        Object ee = GetAnyConst(e.Resolved ?? e, new Stack<ConstantField>());
 03801        return ee as BigInteger?;
 03802      };
 3803      // Now, then, let's go through them types.
 3804      // FIXME - should first go through the bounds to find the most constraining values
 3805      // then check those values against the possible types. Note that also presumes the types are in order.
 03806      BigInteger? lowest = null;
 03807      BigInteger? highest = null;
 03808      foreach (var bound in bounds) {
 03809        if (bound is ComprehensionExpr.IntBoundedPool) {
 03810          var bnd = (ComprehensionExpr.IntBoundedPool)bound;
 03811          if (bnd.LowerBound != null) {
 03812            BigInteger? lower = GetConst(bnd.LowerBound);
 03813            if (lower != null && (lowest == null || lower < lowest)) {
 03814              lowest = lower;
 03815            }
 03816          }
 03817          if (bnd.UpperBound != null) {
 03818            BigInteger? upper = GetConst(bnd.UpperBound);
 03819            if (upper != null && (highest == null || upper > highest)) {
 03820              highest = upper;
 03821            }
 03822          }
 03823        }
 03824      }
 03825      foreach (var nativeT in nativeTypeChoices ?? NativeTypes) {
 03826        bool lowerOk = (lowest != null && nativeT.LowerBound <= lowest);
 03827        bool upperOk = (highest != null && nativeT.UpperBound >= highest);
 03828        if (lowerOk && upperOk) {
 03829          bigEnoughNativeTypes.Add(nativeT);
 03830        } else if (nativeTypeChoices != null) {
 03831          reporter.Error(MessageSource.Resolver, dd,
 03832            "Dafny's heuristics failed to confirm '{0}' to be a compatible native type.  " +
 03833            "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additio
 03834            nativeT.Name);
 03835          return;
 3836        }
 03837      }
 3838
 3839      // Finally, of the big-enough native types, pick the first one that is
 3840      // supported by the selected target compiler.
 03841      foreach (var nativeT in bigEnoughNativeTypes) {
 03842        if (Options.Backend.SupportedNativeTypes.Contains(nativeT.Name)) {
 03843          dd.NativeType = nativeT;
 03844          break;
 3845        }
 03846      }
 03847      if (dd.NativeType != null) {
 3848        // Give an info message saying which type was selected--unless the user requested
 3849        // one particular native type, in which case that must have been the one picked.
 03850        if (nativeTypeChoices != null && nativeTypeChoices.Count == 1) {
 03851          Contract.Assert(dd.NativeType == nativeTypeChoices[0]);
 03852        } else {
 03853          reporter.Info(MessageSource.Resolver, dd.tok, "newtype " + dd.Name + " resolves as {:nativeType \"" + dd.Nativ
 03854        }
 03855      } else if (nativeTypeChoices != null) {
 03856        reporter.Error(MessageSource.Resolver, dd,
 03857          "None of the types given in :nativeType arguments is supported by the current compilation target. Try supplyin
 03858      } else if (mustUseNativeType) {
 03859        reporter.Error(MessageSource.Resolver, dd,
 03860          "Dafny's heuristics cannot find a compatible native type.  " +
 03861          "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additiona
 03862      }
 03863    }
 3864
 3865    /// <summary>
 3866    /// Check that the 'older' modifier on parameters is used correctly and report any errors of the contrary.
 3867    /// </summary>
 03868    void CheckOlderParameters(Function f) {
 3869      Contract.Requires(f != null);
 3870
 03871      if (!f.ResultType.IsBoolType || f is PrefixPredicate || f is ExtremePredicate) {
 3872        // parameters are not allowed to be marked 'older'
 03873        foreach (var formal in f.Formals) {
 03874          if (formal.IsOlder) {
 03875            reporter.Error(MessageSource.Resolver, formal.tok, "only predicates and two-state predicates are allowed 'ol
 03876          }
 03877        }
 03878      }
 03879    }
 3880
 3881    // ------------------------------------------------------------------------------------------------------
 3882    // ----- CheckExpression --------------------------------------------------------------------------------
 3883    // ------------------------------------------------------------------------------------------------------
 3884    #region CheckExpression
 3885    /// <summary>
 3886    /// This method computes ghost interests in the statement portion of StmtExpr's and
 3887    /// checks for hint restrictions in any CalcStmt.
 3888    /// </summary>
 53903889    void CheckExpression(Expression expr, Resolver resolver, ICodeContext codeContext) {
 3890      Contract.Requires(expr != null);
 3891      Contract.Requires(resolver != null);
 3892      Contract.Requires(codeContext != null);
 53903893      var v = new CheckExpression_Visitor(resolver, codeContext);
 53903894      v.Visit(expr);
 53903895    }
 3896    /// <summary>
 3897    /// This method computes ghost interests in the statement portion of StmtExpr's and
 3898    /// checks for hint restrictions in any CalcStmt. In any ghost context, it also
 3899    /// changes the bound variables of all let- and let-such-that expressions to ghost.
 3900    /// It also performs substitutions in DefaultValueExpression's.
 3901    /// </summary>
 48463902    void CheckExpression(Statement stmt, Resolver resolver, ICodeContext codeContext) {
 3903      Contract.Requires(stmt != null);
 3904      Contract.Requires(resolver != null);
 3905      Contract.Requires(codeContext != null);
 48463906      var v = new CheckExpression_Visitor(resolver, codeContext);
 48463907      v.Visit(stmt);
 48463908    }
 3909    class CheckExpression_Visitor : ResolverBottomUpVisitor {
 3910      readonly ICodeContext CodeContext;
 3911      public CheckExpression_Visitor(Resolver resolver, ICodeContext codeContext)
 204723912        : base(resolver) {
 3913        Contract.Requires(resolver != null);
 3914        Contract.Requires(codeContext != null);
 102363915        CodeContext = codeContext;
 102363916      }
 15313683917      protected override void VisitOneExpr(Expression expr) {
 15313683918        if (expr is StmtExpr) {
 03919          var e = (StmtExpr)expr;
 03920          resolver.ComputeGhostInterest(e.S, true, "a statement expression", CodeContext);
 15313683921        } else if (expr is LetExpr) {
 03922          var e = (LetExpr)expr;
 03923          if (CodeContext.IsGhost) {
 03924            foreach (var bv in e.BoundVars) {
 03925              bv.MakeGhost();
 03926            }
 03927          }
 03928        }
 15313683929      }
 3930
 2972863931      protected override void VisitOneStmt(Statement stmt) {
 2972863932        if (stmt is CalcStmt calc) {
 03933          foreach (var h in calc.Hints) {
 03934            resolver.CheckLocalityUpdates(h, new HashSet<LocalVariable>(), "a hint");
 03935          }
 2972863936        } else if (stmt is AssertStmt astmt && astmt.Proof != null) {
 03937          resolver.CheckLocalityUpdates(astmt.Proof, new HashSet<LocalVariable>(), "an assert-by body");
 2972863938        } else if (stmt is ForallStmt forall && forall.Body != null) {
 03939          resolver.CheckLocalityUpdates(forall.Body, new HashSet<LocalVariable>(), "a forall statement");
 03940        }
 2972863941      }
 3942    }
 3943    #endregion
 3944
 3945    // ------------------------------------------------------------------------------------------------------
 3946    // ----- FuelAdjustmentChecks ---------------------------------------------------------------------------
 3947    // ------------------------------------------------------------------------------------------------------
 3948    #region FuelAdjustmentChecks
 3949
 1513423950    protected void CheckForFuelAdjustments(IToken tok, Attributes attrs, ModuleDefinition currentModule) {
 1513423951      List<List<Expression>> results = Attributes.FindAllExpressions(attrs, "fuel");
 3952
 1513423953      if (results != null) {
 03954        foreach (List<Expression> args in results) {
 03955          if (args != null && args.Count >= 2) {
 3956            // Try to extract the function from the first argument
 03957            MemberSelectExpr selectExpr = args[0].Resolved as MemberSelectExpr;
 03958            if (selectExpr != null) {
 03959              Function f = selectExpr.Member as Function;
 03960              if (f != null) {
 03961                f.IsFueled = true;
 03962                if (args.Count >= 3) {
 03963                  LiteralExpr literalLow = args[1] as LiteralExpr;
 03964                  LiteralExpr literalHigh = args[2] as LiteralExpr;
 03965                  if (literalLow != null && literalLow.Value is BigInteger && literalHigh != null && literalHigh.Value i
 03966                    BigInteger low = (BigInteger)literalLow.Value;
 03967                    BigInteger high = (BigInteger)literalHigh.Value;
 03968                    if (!(high == low + 1 || (low == 0 && high == 0))) {
 03969                      reporter.Error(MessageSource.Resolver, tok, "fuel setting for function {0} must have high value ==
 03970                    }
 03971                  }
 03972                }
 03973              }
 03974            }
 03975          }
 03976        }
 03977      }
 1513423978    }
 3979
 3980    public class FuelAdjustment_Context {
 3981      public ModuleDefinition currentModule;
 48463982      public FuelAdjustment_Context(ModuleDefinition currentModule) {
 24233983        this.currentModule = currentModule;
 24233984      }
 3985    }
 3986
 3987    class FuelAdjustment_Visitor : ResolverTopDownVisitor<FuelAdjustment_Context> {
 3988      public FuelAdjustment_Visitor(Resolver resolver)
 48463989        : base(resolver) {
 3990        Contract.Requires(resolver != null);
 24233991      }
 3992
 1486433993      protected override bool VisitOneStmt(Statement stmt, ref FuelAdjustment_Context st) {
 1486433994        resolver.CheckForFuelAdjustments(stmt.Tok, stmt.Attributes, st.currentModule);
 1486433995        return true;
 1486433996      }
 3997    }
 3998
 3999    #endregion FuelAdjustmentChecks
 4000
 4001    // ------------------------------------------------------------------------------------------------------
 4002    // ----- ExtremePredicateChecks -------------------------------------------------------------------------
 4003    // ------------------------------------------------------------------------------------------------------
 4004    #region ExtremePredicateChecks
 4005    enum CallingPosition { Positive, Negative, Neither }
 04006    static CallingPosition Invert(CallingPosition cp) {
 04007      switch (cp) {
 04008        case CallingPosition.Positive: return CallingPosition.Negative;
 04009        case CallingPosition.Negative: return CallingPosition.Positive;
 04010        default: return CallingPosition.Neither;
 4011      }
 04012    }
 4013
 4014    class FindFriendlyCalls_Visitor : ResolverTopDownVisitor<CallingPosition> {
 4015      public readonly bool IsCoContext;
 4016      public readonly bool ContinuityIsImportant;
 4017      public FindFriendlyCalls_Visitor(Resolver resolver, bool co, bool continuityIsImportant)
 04018        : base(resolver) {
 4019        Contract.Requires(resolver != null);
 04020        this.IsCoContext = co;
 04021        this.ContinuityIsImportant = continuityIsImportant;
 04022      }
 4023
 04024      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 04025        if (expr is UnaryOpExpr) {
 04026          var e = (UnaryOpExpr)expr;
 04027          if (e.Op == UnaryOpExpr.Opcode.Not) {
 4028            // for the sub-parts, use Invert(cp)
 04029            cp = Invert(cp);
 04030            return true;
 4031          }
 04032        } else if (expr is BinaryExpr) {
 04033          var e = (BinaryExpr)expr;
 04034          switch (e.ResolvedOp) {
 4035            case BinaryExpr.ResolvedOpcode.And:
 4036            case BinaryExpr.ResolvedOpcode.Or:
 04037              return true;  // do the sub-parts with the same "cp"
 4038            case BinaryExpr.ResolvedOpcode.Imp:
 04039              Visit(e.E0, Invert(cp));
 04040              Visit(e.E1, cp);
 04041              return false;  // don't recurse (again) on the sub-parts
 4042            default:
 04043              break;
 4044          }
 04045        } else if (expr is NestedMatchExpr) {
 04046          var e = (NestedMatchExpr)expr;
 04047          Visit(e.Source, CallingPosition.Neither);
 04048          var theCp = cp;
 04049          e.Cases.Iter(kase => Visit(kase.Body, theCp));
 04050          return false;
 04051        } else if (expr is MatchExpr) {
 04052          var e = (MatchExpr)expr;
 04053          Visit(e.Source, CallingPosition.Neither);
 04054          var theCp = cp;
 04055          e.Cases.Iter(kase => Visit(kase.Body, theCp));
 04056          return false;
 04057        } else if (expr is ITEExpr) {
 04058          var e = (ITEExpr)expr;
 04059          Visit(e.Test, CallingPosition.Neither);
 04060          Visit(e.Thn, cp);
 04061          Visit(e.Els, cp);
 04062          return false;
 04063        } else if (expr is LetExpr) {
 04064          var e = (LetExpr)expr;
 04065          foreach (var rhs in e.RHSs) {
 04066            Visit(rhs, CallingPosition.Neither);
 04067          }
 04068          var cpBody = cp;
 04069          if (!e.Exact) {
 4070            // a let-such-that expression introduces an existential that may depend on the _k in a least/greatest predic
 04071            if (IsCoContext && cp == CallingPosition.Positive) {
 04072              cpBody = CallingPosition.Neither;
 04073            } else if (!IsCoContext && cp == CallingPosition.Negative) {
 04074              cpBody = CallingPosition.Neither;
 04075            }
 04076          }
 04077          Visit(e.Body, cpBody);
 04078          return false;
 04079        } else if (expr is QuantifierExpr) {
 04080          var e = (QuantifierExpr)expr;
 04081          Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 04082          var cpos = IsCoContext ? cp : Invert(cp);
 04083          if (ContinuityIsImportant) {
 04084            if ((cpos == CallingPosition.Positive && e is ExistsExpr) || (cpos == CallingPosition.Negative && e is Foral
 04085              if (e.Bounds.Exists(bnd => bnd == null || (bnd.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite)
 4086                // To ensure continuity of extreme predicates, don't allow calls under an existential (resp. universal) 
 4087                // for greatest (resp. least) predicates).
 04088                cp = CallingPosition.Neither;
 04089              }
 04090            }
 04091          }
 04092          Visit(e.LogicalBody(), cp);
 04093          return false;
 04094        } else if (expr is StmtExpr) {
 04095          var e = (StmtExpr)expr;
 04096          Visit(e.E, cp);
 04097          Visit(e.S, CallingPosition.Neither);
 04098          return false;
 04099        } else if (expr is ConcreteSyntaxExpression) {
 4100          // do the sub-parts with the same "cp"
 04101          return true;
 4102        }
 4103        // do the sub-parts with cp := Neither
 04104        cp = CallingPosition.Neither;
 04105        return true;
 04106      }
 4107    }
 4108
 04109    void KNatMismatchError(IToken tok, string contextName, ExtremePredicate.KType contextK, ExtremePredicate.KType calle
 04110      var hint = contextK == ExtremePredicate.KType.Unspecified ? string.Format(" (perhaps try declaring '{0}' as '{0}[n
 04111      reporter.Error(MessageSource.Resolver, tok,
 04112        "this call does not type check, because the context uses a _k parameter of type {0} whereas the callee uses a _k
 04113        contextK == ExtremePredicate.KType.Nat ? "nat" : "ORDINAL",
 04114        calleeK == ExtremePredicate.KType.Nat ? "nat" : "ORDINAL",
 04115        hint);
 04116    }
 4117
 4118    class ExtremePredicateChecks_Visitor : FindFriendlyCalls_Visitor {
 4119      readonly ExtremePredicate context;
 4120      public ExtremePredicateChecks_Visitor(Resolver resolver, ExtremePredicate context)
 04121        : base(resolver, context is GreatestPredicate, context.KNat) {
 4122        Contract.Requires(resolver != null);
 4123        Contract.Requires(context != null);
 04124        this.context = context;
 04125      }
 04126      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 04127        if (expr is FunctionCallExpr) {
 04128          var e = (FunctionCallExpr)expr;
 04129          if (ModuleDefinition.InSameSCC(context, e.Function)) {
 4130            // we're looking at a recursive call
 04131            if (!(context is LeastPredicate ? e.Function is LeastPredicate : e.Function is GreatestPredicate)) {
 04132              resolver.reporter.Error(MessageSource.Resolver, e, "a recursive call from a {0} can go only to other {0}s"
 04133            } else if (context.KNat != ((ExtremePredicate)e.Function).KNat) {
 04134              resolver.KNatMismatchError(e.tok, context.Name, context.TypeOfK, ((ExtremePredicate)e.Function).TypeOfK);
 04135            } else if (cp != CallingPosition.Positive) {
 04136              var msg = string.Format("a {0} can be called recursively only in positive positions", context.WhatKind);
 04137              if (ContinuityIsImportant && cp == CallingPosition.Neither) {
 4138                // this may be inside an non-friendly quantifier
 04139                msg += string.Format(" and cannot sit inside an unbounded {0} quantifier", context is LeastPredicate ? "
 04140              } else {
 4141                // we don't care about the continuity restriction or
 4142                // the extreme-call is not inside an quantifier, so don't bother mentioning the part of existentials/uni
 04143              }
 04144              resolver.reporter.Error(MessageSource.Resolver, e, msg);
 04145            } else {
 04146              e.CoCall = FunctionCallExpr.CoCallResolution.Yes;
 04147              resolver.reporter.Info(MessageSource.Resolver, e.tok, e.Function.Name + "#[_k - 1]");
 04148            }
 04149          }
 4150          // do the sub-parts with cp := Neither
 04151          cp = CallingPosition.Neither;
 04152          return true;
 4153        }
 04154        return base.VisitOneExpr(expr, ref cp);
 04155      }
 04156      protected override bool VisitOneStmt(Statement stmt, ref CallingPosition st) {
 04157        if (stmt is CallStmt) {
 04158          var s = (CallStmt)stmt;
 04159          if (ModuleDefinition.InSameSCC(context, s.Method)) {
 4160            // we're looking at a recursive call
 04161            resolver.reporter.Error(MessageSource.Resolver, stmt.Tok, "a recursive call from a {0} can go only to other 
 04162          }
 4163          // do the sub-parts with the same "cp"
 04164          return true;
 04165        } else {
 04166          return base.VisitOneStmt(stmt, ref st);
 4167        }
 04168      }
 4169    }
 4170
 04171    void ExtremePredicateChecks(Expression expr, ExtremePredicate context, CallingPosition cp) {
 4172      Contract.Requires(expr != null);
 4173      Contract.Requires(context != null);
 04174      var v = new ExtremePredicateChecks_Visitor(this, context);
 04175      v.Visit(expr, cp);
 04176    }
 4177    #endregion ExtremePredicateChecks
 4178
 4179    // ------------------------------------------------------------------------------------------------------
 4180    // ----- ExtremeLemmaChecks -----------------------------------------------------------------------------
 4181    // ------------------------------------------------------------------------------------------------------
 4182    #region ExtremeLemmaChecks
 4183    class ExtremeLemmaChecks_Visitor : ResolverBottomUpVisitor {
 4184      ExtremeLemma context;
 4185      public ExtremeLemmaChecks_Visitor(Resolver resolver, ExtremeLemma context)
 04186        : base(resolver) {
 4187        Contract.Requires(resolver != null);
 4188        Contract.Requires(context != null);
 04189        this.context = context;
 04190      }
 04191      protected override void VisitOneStmt(Statement stmt) {
 04192        if (stmt is CallStmt) {
 04193          var s = (CallStmt)stmt;
 04194          if (s.Method is ExtremeLemma || s.Method is PrefixLemma) {
 4195            // all is cool
 04196          } else {
 4197            // the call goes from an extreme lemma context to a non-extreme-lemma callee
 04198            if (ModuleDefinition.InSameSCC(context, s.Method)) {
 4199              // we're looking at a recursive call (to a non-extreme-lemma)
 04200              resolver.reporter.Error(MessageSource.Resolver, s.Tok, "a recursive call from a {0} can go only to other {
 04201            }
 04202          }
 04203        }
 04204      }
 04205      protected override void VisitOneExpr(Expression expr) {
 04206        if (expr is FunctionCallExpr) {
 04207          var e = (FunctionCallExpr)expr;
 4208          // the call goes from a greatest lemma context to a non-greatest-lemma callee
 04209          if (ModuleDefinition.InSameSCC(context, e.Function)) {
 4210            // we're looking at a recursive call (to a non-greatest-lemma)
 04211            resolver.reporter.Error(MessageSource.Resolver, e.tok, "a recursive call from a greatest lemma can go only t
 04212          }
 04213        }
 04214      }
 4215    }
 04216    void ExtremeLemmaChecks(Statement stmt, ExtremeLemma context) {
 4217      Contract.Requires(stmt != null);
 4218      Contract.Requires(context != null);
 04219      var v = new ExtremeLemmaChecks_Visitor(this, context);
 04220      v.Visit(stmt);
 04221    }
 04222    void ExtremeLemmaChecks(Expression expr, ExtremeLemma context) {
 4223      Contract.Requires(context != null);
 04224      if (expr == null) {
 04225        return;
 4226      }
 4227
 04228      var v = new ExtremeLemmaChecks_Visitor(this, context);
 04229      v.Visit(expr);
 04230    }
 4231    #endregion ExtremeLemmaChecks
 4232
 4233    // ------------------------------------------------------------------------------------------------------
 4234    // ----- CheckTypeCharacteristics -----------------------------------------------------------------------
 4235    // ------------------------------------------------------------------------------------------------------
 4236    #region CheckTypeCharacteristics
 48464237    void CheckTypeCharacteristics_Stmt(Statement stmt, bool isGhost) {
 4238      Contract.Requires(stmt != null);
 48464239      var v = new CheckTypeCharacteristics_Visitor(this);
 48464240      v.Visit(stmt, isGhost);
 48464241    }
 12244242    void CheckTypeCharacteristics_Expr(Expression expr, bool isGhost) {
 4243      Contract.Requires(expr != null);
 12244244      var v = new CheckTypeCharacteristics_Visitor(this);
 12244245      v.Visit(expr, isGhost);
 12244246    }
 173444247    public void CheckTypeCharacteristics_Type(IToken tok, Type type, bool isGhost) {
 4248      Contract.Requires(tok != null);
 4249      Contract.Requires(type != null);
 173444250      var v = new CheckTypeCharacteristics_Visitor(this);
 173444251      v.VisitType(tok, type, isGhost);
 173444252    }
 4253
 4254    /// <summary>
 4255    /// This visitor checks that type characteristics are respected in all (implicitly or explicitly)
 4256    /// declared types. Note that equality-support is checked only in compiled contexts.
 4257    /// In addition, this visitor checks that operations that require equality are applied to
 4258    /// types that really do support equality; this, too, is checked only in compiled contexts.
 4259    /// </summary>
 4260    class CheckTypeCharacteristics_Visitor : ResolverTopDownVisitor<bool> {
 4261      public CheckTypeCharacteristics_Visitor(Resolver resolver)
 468284262        : base(resolver) {
 4263        Contract.Requires(resolver != null);
 234144264      }
 2972864265      protected override bool VisitOneStmt(Statement stmt, ref bool inGhostContext) {
 2989204266        if (stmt.IsGhost) {
 16344267          inGhostContext = true;
 16344268        }
 4269        // In the sequel, do two things:
 4270        //  * Call VisitType on any type that occurs in the statement
 4271        //  * If the statement introduces ghost components, handle those components here
 4272        //    rather than letting the default visitor handle them
 3830364273        if (stmt is VarDeclStmt) {
 857504274          var s = (VarDeclStmt)stmt;
 5241064275          foreach (var v in s.Locals) {
 889524276            VisitType(v.Tok, v.Type, inGhostContext || v.IsGhost);
 889524277          }
 2972864278        } else if (stmt is VarDeclPattern) {
 04279          var s = (VarDeclPattern)stmt;
 04280          foreach (var v in s.LocalVars) {
 04281            VisitType(v.Tok, v.Type, inGhostContext || v.IsGhost);
 04282          }
 3014864283        } else if (stmt is AssignStmt) {
 899504284          var s = (AssignStmt)stmt;
 955644285          if (s.Rhs is TypeRhs tRhs) {
 56144286            VisitType(tRhs.Tok, tRhs.Type, inGhostContext);
 56144287          }
 2115364288        } else if (stmt is AssignSuchThatStmt) {
 04289          var s = (AssignSuchThatStmt)stmt;
 04290          Visit(Attributes.SubExpressions(s.Attributes), true);
 04291          Visit(s.Expr, inGhostContext);
 04292          foreach (var lhs in s.Lhss) {
 04293            Visit(lhs, inGhostContext);
 04294          }
 04295          return false;
 1221964296        } else if (stmt is WhileStmt) {
 6104297          var s = (WhileStmt)stmt;
 4298          // all subexpressions are ghost, except the guard
 6104299          Visit(s.LoopSpecificationExpressions, true);
 12204300          if (s.Guard != null) {
 6104301            Visit(s.Guard, inGhostContext);
 6104302          }
 6104303          Visit(s.SubStatements, inGhostContext);
 6104304          return false;
 1209764305        } else if (stmt is AlternativeLoopStmt) {
 04306          var s = (AlternativeLoopStmt)stmt;
 4307          // all subexpressions are ghost, except the guards
 04308          Visit(s.LoopSpecificationExpressions, true);
 04309          foreach (var alt in s.Alternatives) {
 04310            Visit(alt.Guard, inGhostContext);
 04311          }
 04312          Visit(s.SubStatements, inGhostContext);
 04313          return false;
 1215584314        } else if (stmt is ForLoopStmt) {
 5824315          var s = (ForLoopStmt)stmt;
 4316          // all subexpressions are ghost, except the bounds
 5824317          Visit(s.LoopSpecificationExpressions, true);
 5824318          Visit(s.Start, inGhostContext);
 11644319          if (s.End != null) {
 5824320            Visit(s.End, inGhostContext);
 5824321          }
 5824322          Visit(s.SubStatements, inGhostContext);
 5824323          return false;
 1268804324        } else if (stmt is CallStmt) {
 64864325          var s = (CallStmt)stmt;
 64864326          CheckTypeInstantiation(s.Tok, s.Method.WhatKind, s.Method.Name, s.Method.TypeArgs, s.MethodSelect.TypeApplicat
 4327          // recursively visit all subexpressions, noting that some of them may correspond to ghost formal parameters
 64864328          Contract.Assert(s.Lhs.Count == s.Method.Outs.Count);
 333484329          for (var i = 0; i < s.Method.Outs.Count; i++) {
 67924330            Visit(s.Lhs[i], inGhostContext || s.Method.Outs[i].IsGhost);
 67924331          }
 64864332          Visit(s.Receiver, inGhostContext);
 64864333          Contract.Assert(s.Args.Count == s.Method.Ins.Count);
 566524334          for (var i = 0; i < s.Method.Ins.Count; i++) {
 145604335            Visit(s.Args[i], inGhostContext || s.Method.Ins[i].IsGhost);
 145604336          }
 64864337          return false;
 1139084338        } else if (stmt is ForallStmt) {
 04339          var s = (ForallStmt)stmt;
 04340          foreach (var v in s.BoundVars) {
 04341            VisitType(v.Tok, v.Type, inGhostContext);
 04342          }
 4343          // do substatements and subexpressions, noting that ensures clauses are ghost
 04344          Visit(Attributes.SubExpressions(s.Attributes), true);
 04345          if (s.Range != null) {
 04346            Visit(s.Range, inGhostContext);
 04347          }
 04348          foreach (var ee in s.Ens) {
 04349            Visit(Attributes.SubExpressions(ee.Attributes), true);
 04350            Visit(ee.E, true);
 04351          }
 04352          Visit(s.SubStatements, inGhostContext);
 04353          return false;
 1148384354        } else if (stmt is ExpectStmt) {
 9304355          var s = (ExpectStmt)stmt;
 9304356          Visit(Attributes.SubExpressions(s.Attributes), true);
 9304357          Visit(s.Expr, inGhostContext);
 18604358          if (s.Message != null) {
 9304359            Visit(s.Message, inGhostContext);
 9304360          }
 9304361          return false;
 4362        }
 2886784363        return true;
 2972864364      }
 4365
 12550134366      protected override bool VisitOneExpr(Expression expr, ref bool inGhostContext) {
 4367        // Do two things:
 4368        //  * Call VisitType on any type that occurs in the statement
 4369        //  * If the expression introduces ghost components, handle those components here
 4370        //    rather than letting the default visitor handle them
 13054574371        if (expr is BinaryExpr && !inGhostContext) {
 504444372          var e = (BinaryExpr)expr;
 504444373          var t0 = e.E0.Type.NormalizeExpand();
 504444374          var t1 = e.E1.Type.NormalizeExpand();
 504444375          switch (e.Op) {
 4376            case BinaryExpr.Opcode.Eq:
 4377            case BinaryExpr.Opcode.Neq:
 4378              // First, check some special cases that can always be compared against--for example, a datatype value (lik
 465764379              if (CanCompareWith(e.E0)) {
 4380                // that's cool
 232884381              } else if (CanCompareWith(e.E1)) {
 4382                // oh yeah!
 04383              } else if (!t0.PartiallySupportsEquality) {
 04384                resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of types t
 04385              } else if (!t1.PartiallySupportsEquality) {
 04386                resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of types t
 04387              }
 232884388              break;
 4389            default:
 271564390              switch (e.ResolvedOp) {
 4391                // Note, all operations on sets, multisets, and maps are guaranteed to work because of restrictions plac
 4392                // these types are instantiated.  (Except: This guarantee does not apply to equality on maps, because th
 4393                // of maps is not restricted, only the Domain type.  However, the equality operator is checked above.)
 4394                case BinaryExpr.ResolvedOpcode.InSeq:
 4395                case BinaryExpr.ResolvedOpcode.NotInSeq:
 4396                case BinaryExpr.ResolvedOpcode.Prefix:
 4397                case BinaryExpr.ResolvedOpcode.ProperPrefix:
 924398                  if (!t1.SupportsEquality) {
 04399                    resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of seq
 924400                  } else if (!t0.SupportsEquality) {
 04401                    if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.InSet || e.ResolvedOp == BinaryExpr.ResolvedOpcode.Not
 04402                      resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of t
 04403                    } else {
 04404                      resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of s
 04405                    }
 04406                  }
 924407                  break;
 4408                default:
 270644409                  break;
 4410              }
 271564411              break;
 4412          }
 12550134413        } else if (expr is ComprehensionExpr) {
 04414          var e = (ComprehensionExpr)expr;
 04415          foreach (var bv in e.BoundVars) {
 04416            VisitType(bv.tok, bv.Type, inGhostContext);
 04417          }
 12045694418        } else if (expr is LetExpr) {
 04419          var e = (LetExpr)expr;
 04420          Visit(Attributes.SubExpressions(e.Attributes), true);
 04421          if (e.Exact) {
 04422            Contract.Assert(e.LHSs.Count == e.RHSs.Count);
 04423            for (var i = 0; i < e.LHSs.Count; i++) {
 4424              // The VisitPattern function visits all BoundVar's in a pattern and returns
 4425              // "true" if all variables are ghost.
 04426              bool VisitPattern(CasePattern<BoundVar> pat, bool patternGhostContext) {
 04427                if (pat.Var != null) {
 04428                  VisitType(pat.tok, pat.Var.Type, patternGhostContext || pat.Var.IsGhost);
 04429                  return pat.Var.IsGhost;
 04430                } else {
 04431                  var allGhost = true;
 04432                  Contract.Assert(pat.Ctor != null);
 04433                  Contract.Assert(pat.Ctor.Formals.Count == pat.Arguments.Count);
 04434                  for (var i = 0; i < pat.Ctor.Formals.Count; i++) {
 04435                    var formal = pat.Ctor.Formals[i];
 04436                    var arg = pat.Arguments[i];
 4437                    // don't use short-circuit booleans in the following line, because we want to visit all nested patte
 04438                    allGhost &= VisitPattern(arg, patternGhostContext || formal.IsGhost);
 04439                  }
 04440                  return allGhost;
 4441                }
 04442              }
 4443
 04444              var allGhosts = VisitPattern(e.LHSs[i], inGhostContext);
 04445              Visit(e.RHSs[i], inGhostContext || allGhosts);
 04446            }
 04447          } else {
 04448            Contract.Assert(e.RHSs.Count == 1);
 04449            var allGhost = true;
 04450            foreach (var bv in e.BoundVars) {
 04451              if (!bv.IsGhost) {
 04452                allGhost = false;
 04453              }
 04454              VisitType(bv.tok, bv.Type, inGhostContext || bv.IsGhost);
 04455            }
 04456            Visit(e.RHSs[0], inGhostContext || allGhost);
 04457          }
 04458          Visit(e.Body, inGhostContext);
 04459          return false;
 12177194460        } else if (expr is MemberSelectExpr) {
 131504461          var e = (MemberSelectExpr)expr;
 131504462          if (e.Member is Function || e.Member is Method) {
 04463            CheckTypeInstantiation(e.tok, e.Member.WhatKind, e.Member.Name, ((ICallable)e.Member).TypeArgs, e.TypeApplic
 04464          }
 12045694465        } else if (expr is FunctionCallExpr) {
 04466          var e = (FunctionCallExpr)expr;
 04467          CheckTypeInstantiation(e.tok, e.Function.WhatKind, e.Function.Name, e.Function.TypeArgs, e.TypeApplication_Jus
 4468          // recursively visit all subexpressions (all actual parameters), noting which ones correspond to ghost formal 
 04469          Visit(e.Receiver, inGhostContext);
 04470          Contract.Assert(e.Args.Count == e.Function.Formals.Count);
 04471          for (var i = 0; i < e.Args.Count; i++) {
 04472            Visit(e.Args[i], inGhostContext || e.Function.Formals[i].IsGhost);
 04473          }
 04474          return false;  // we've done what there is to be done
 12143334475        } else if (expr is DatatypeValue) {
 229144476          var e = (DatatypeValue)expr;
 4477          // recursively visit all subexpressions (all actual parameters), noting which ones correspond to ghost formal 
 229144478          Contract.Assert(e.Arguments.Count == e.Ctor.Formals.Count);
 1878784479          for (var i = 0; i < e.Arguments.Count; i++) {
 473504480            Visit(e.Arguments[i], inGhostContext || e.Ctor.Formals[i].IsGhost);
 473504481          }
 229144482          return false;  // we've done what there is to be done
 11685054483        } else if (expr is SetDisplayExpr || expr is MultiSetDisplayExpr || expr is MapDisplayExpr || expr is SeqConstru
 12152494484                   expr is MultiSetFormingExpr || expr is StaticReceiverExpr) {
 4485          // This catches other expressions whose type may potentially be illegal
 467444486          VisitType(expr.tok, expr.Type, inGhostContext);
 11685054487        } else if (expr is StmtExpr) {
 04488          var e = (StmtExpr)expr;
 04489          Visit(e.S, true);
 04490          Visit(e.E, inGhostContext);
 04491          return false;
 4492        }
 12320994493        return true;
 12550134494      }
 4495
 3622464496      public void VisitType(IToken tok, Type type, bool inGhostContext) {
 4497        Contract.Requires(tok != null);
 4498        Contract.Requires(type != null);
 3622464499        type = type.Normalize();  // we only do a .Normalize() here, because we want to keep stop at any type synonym or
 5762024500        if (type is BasicType) {
 4501          // fine
 3783984502        } else if (type is SetType) {
 161524503          var st = (SetType)type;
 161524504          var argType = st.Arg;
 161524505          if (!inGhostContext && !argType.SupportsEquality) {
 04506            resolver.reporter.Error(MessageSource.Resolver, tok, "{2}set argument type must support equality (got {0}){1
 04507          }
 161524508          VisitType(tok, argType, inGhostContext);
 4509
 1667124510        } else if (type is MultiSetType) {
 184224511          var argType = ((MultiSetType)type).Arg;
 184224512          if (!inGhostContext && !argType.SupportsEquality) {
 04513            resolver.reporter.Error(MessageSource.Resolver, tok, "multiset argument type must support equality (got {0})
 4514
 04515          }
 184224516          VisitType(tok, argType, inGhostContext);
 1596844517        } else if (type is MapType) {
 275464518          var mt = (MapType)type;
 275464519          if (!inGhostContext && !mt.Domain.SupportsEquality) {
 04520            resolver.reporter.Error(MessageSource.Resolver, tok, "{2}map domain type must support equality (got {0}){1}"
 04521          }
 275464522          VisitType(tok, mt.Domain, inGhostContext);
 275464523          VisitType(tok, mt.Range, inGhostContext);
 4524
 1363884525        } else if (type is SeqType) {
 226724526          Type argType = ((SeqType)type).Arg;
 226724527          VisitType(tok, argType, inGhostContext);
 4528
 1496684529        } else if (type is UserDefinedType) {
 634984530          var udt = (UserDefinedType)type;
 634984531          Contract.Assert(udt.ResolvedClass != null);
 634984532          var formalTypeArgs = udt.ResolvedClass.TypeArgs;
 634984533          Contract.Assert(formalTypeArgs != null);
 634984534          CheckTypeInstantiation(udt.tok, "type", udt.ResolvedClass.Name, formalTypeArgs, udt.TypeArgs, inGhostContext);
 4535
 634984536        } else if (type is TypeProxy) {
 4537          // the type was underconstrained; this is checked elsewhere, but it is not in violation of the equality-type t
 04538        } else {
 04539          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4540        }
 3622464541      }
 4542
 699844543      void CheckTypeInstantiation(IToken tok, string what, string className, List<TypeParameter> formalTypeArgs, List<Ty
 4544        Contract.Requires(tok != null);
 4545        Contract.Requires(what != null);
 4546        Contract.Requires(className != null);
 4547        Contract.Requires(formalTypeArgs != null);
 4548        Contract.Requires(actualTypeArgs != null);
 4549        Contract.Requires(formalTypeArgs.Count == actualTypeArgs.Count);
 4550
 4137304551        for (var i = 0; i < formalTypeArgs.Count; i++) {
 912544552          var formal = formalTypeArgs[i];
 912544553          var actual = actualTypeArgs[i];
 912544554          if (!CheckCharacteristics(formal.Characteristics, actual, inGhostContext, out var whatIsWrong, out var hint)) 
 04555            resolver.reporter.Error(MessageSource.Resolver, tok, "type parameter{0} ({1}) passed to {2} {3} must support
 04556              actualTypeArgs.Count == 1 ? "" : " " + i, formal.Name, what, className, whatIsWrong, actual, hint);
 04557          }
 912544558          VisitType(tok, actual, inGhostContext);
 912544559        }
 699844560      }
 4561
 912544562      bool CheckCharacteristics(TypeParameter.TypeParameterCharacteristics formal, Type actual, bool inGhostContext, out
 4563        Contract.Ensures(Contract.Result<bool>() || (Contract.ValueAtReturn(out whatIsWrong) != null && Contract.ValueAt
 912544564        if (!inGhostContext && formal.EqualitySupport != TypeParameter.EqualitySupportValue.Unspecified && !actual.Suppo
 04565          whatIsWrong = "equality";
 04566          hint = TypeEqualityErrorMessageHint(actual);
 04567          return false;
 4568        }
 912544569        var cl = (actual.Normalize() as UserDefinedType)?.ResolvedClass;
 912544570        var tp = (TopLevelDecl)(cl as TypeParameter) ?? cl as AbstractTypeDecl;
 912544571        if (formal.HasCompiledValue && (inGhostContext ? !actual.IsNonempty : !actual.HasCompilableValue)) {
 04572          whatIsWrong = "auto-initialization";
 04573          hint = tp == null ? "" :
 04574            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(0)', which says it can only be instanti
 04575          return false;
 4576        }
 912544577        if (formal.IsNonempty && !actual.IsNonempty) {
 04578          whatIsWrong = "nonempty";
 04579          hint = tp == null ? "" :
 04580            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(00)', which says it can only be instant
 04581          return false;
 4582        }
 912544583        if (formal.ContainsNoReferenceTypes && actual.MayInvolveReferences) {
 04584          whatIsWrong = "no references";
 04585          hint = tp == null ? "" :
 04586            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(!new)', which says it can only be insta
 04587          return false;
 4588        }
 912544589        whatIsWrong = null;
 912544590        hint = null;
 912544591        return true;
 912544592      }
 4593
 04594      string TypeEqualityErrorMessageHint(Type argType) {
 4595        Contract.Requires(argType != null);
 04596        var cl = (argType.Normalize() as UserDefinedType)?.ResolvedClass;
 04597        var tp = (TopLevelDecl)(cl as TypeParameter) ?? cl as AbstractTypeDecl;
 04598        if (tp != null) {
 04599          return string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(==)', which says it can only be in
 4600        }
 04601        return "";
 04602      }
 4603    }
 4604
 320214605    public static bool CanCompareWith(Expression expr) {
 4606      Contract.Requires(expr != null);
 640424607      if (expr.Type.SupportsEquality) {
 320214608        return true;
 4609      }
 04610      expr = expr.Resolved;
 04611      if (expr is DatatypeValue datatypeValue && !datatypeValue.Ctor.EnclosingDatatype.HasGhostVariant) {
 04612        for (var i = 0; i < datatypeValue.Ctor.Formals.Count; i++) {
 04613          if (datatypeValue.Ctor.Formals[i].IsGhost) {
 04614            return false;
 04615          } else if (!CanCompareWith(datatypeValue.Arguments[i])) {
 04616            return false;
 4617          }
 04618        }
 04619        return true;
 04620      } else if (expr is DisplayExpression) {
 04621        var e = (DisplayExpression)expr;
 04622        return e.Elements.Count == 0;
 04623      } else if (expr is MapDisplayExpr) {
 04624        var e = (MapDisplayExpr)expr;
 04625        return e.Elements.Count == 0;
 4626      }
 04627      return false;
 320214628    }
 4629
 4630    #endregion CheckTypeCharacteristics
 4631
 4632    // ------------------------------------------------------------------------------------------------------
 4633    // ----- ComputeGhostInterest ---------------------------------------------------------------------------
 4634    // ------------------------------------------------------------------------------------------------------
 4635    #region ComputeGhostInterest
 48464636    public void ComputeGhostInterest(Statement stmt, bool mustBeErasable, [CanBeNull] string proofContext, ICodeContext 
 4637      Contract.Requires(stmt != null);
 4638      Contract.Requires(codeContext != null);
 48464639      var visitor = new GhostInterestVisitor(codeContext, this, reporter, false, codeContext is Method);
 48464640      visitor.Visit(stmt, mustBeErasable, proofContext);
 48464641    }
 4642
 4643    #endregion
 4644
 4645    // ------------------------------------------------------------------------------------------------------
 4646    // ----- FillInDefaultLoopDecreases ---------------------------------------------------------------------
 4647    // ------------------------------------------------------------------------------------------------------
 4648    #region FillInDefaultLoopDecreases
 4649    class FillInDefaultLoopDecreases_Visitor : ResolverBottomUpVisitor {
 4650      readonly ICallable EnclosingMethod;
 4651      public FillInDefaultLoopDecreases_Visitor(Resolver resolver, ICallable enclosingMethod)
 48464652        : base(resolver) {
 4653        Contract.Requires(resolver != null);
 4654        Contract.Requires(enclosingMethod != null);
 24234655        EnclosingMethod = enclosingMethod;
 24234656      }
 1486434657      protected override void VisitOneStmt(Statement stmt) {
 1489484658        if (stmt is WhileStmt) {
 3054659          var s = (WhileStmt)stmt;
 3054660          resolver.FillInDefaultLoopDecreases(s, s.Guard, s.Decreases.Expressions, EnclosingMethod);
 1486434661        } else if (stmt is AlternativeLoopStmt) {
 04662          var s = (AlternativeLoopStmt)stmt;
 04663          resolver.FillInDefaultLoopDecreases(s, null, s.Decreases.Expressions, EnclosingMethod);
 04664        }
 1486434665      }
 4666    }
 4667    #endregion FillInDefaultLoopDecreases
 4668
 4669    // ------------------------------------------------------------------------------------------------------
 4670    // ----- ReportMoreAdditionalInformation ----------------------------------------------------------------
 4671    // ------------------------------------------------------------------------------------------------------
 4672    #region ReportOtherAdditionalInformation_Visitor
 4673    class ReportOtherAdditionalInformation_Visitor : ResolverBottomUpVisitor {
 4674      public ReportOtherAdditionalInformation_Visitor(Resolver resolver)
 48464675        : base(resolver) {
 4676        Contract.Requires(resolver != null);
 24234677      }
 1486434678      protected override void VisitOneStmt(Statement stmt) {
 1486434679        if (stmt is ForallStmt) {
 04680          var s = (ForallStmt)stmt;
 04681          if (s.Kind == ForallStmt.BodyKind.Call) {
 04682            var cs = (CallStmt)s.S0;
 4683            // show the callee's postcondition as the postcondition of the 'forall' statement
 4684            // TODO:  The following substitutions do not correctly take into consideration variable capture; hence, what
 04685            var argsSubstMap = new Dictionary<IVariable, Expression>();  // maps formal arguments to actuals
 04686            Contract.Assert(cs.Method.Ins.Count == cs.Args.Count);
 04687            for (int i = 0; i < cs.Method.Ins.Count; i++) {
 04688              argsSubstMap.Add(cs.Method.Ins[i], cs.Args[i]);
 04689            }
 04690            var substituter = new AlphaConvertingSubstituter(cs.Receiver, argsSubstMap, new Dictionary<TypeParameter, Ty
 04691            if (!Attributes.Contains(s.Attributes, "auto_generated")) {
 04692              foreach (var ens in cs.Method.Ens) {
 04693                var p = substituter.Substitute(ens.E);  // substitute the call's actuals for the method's formals
 04694                resolver.reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(resolver.Options
 04695              }
 04696            }
 04697          }
 04698        }
 1486434699      }
 4700    }
 4701    #endregion ReportOtherAdditionalInformation_Visitor
 4702
 4703    // ------------------------------------------------------------------------------------------------------
 4704    // ----- ReportMoreAdditionalInformation ----------------------------------------------------------------
 4705    // ------------------------------------------------------------------------------------------------------
 4706    #region CheckDividedConstructorInit
 4707    class CheckDividedConstructorInit_Visitor : ResolverTopDownVisitor<int> {
 4708      public CheckDividedConstructorInit_Visitor(Resolver resolver)
 17164709        : base(resolver) {
 4710        Contract.Requires(resolver != null);
 8584711      }
 04712      public void CheckInit(List<Statement> initStmts) {
 4713        Contract.Requires(initStmts != null);
 04714        initStmts.Iter(CheckInit);
 04715      }
 4716      /// <summary>
 4717      /// This method almost does what Visit(Statement) does, except that it handles assignments to
 4718      /// fields differently.
 4719      /// </summary>
 04720      void CheckInit(Statement stmt) {
 4721        Contract.Requires(stmt != null);
 4722        // Visit(stmt) would do:
 4723        //     stmt.SubExpressions.Iter(Visit);    (*)
 4724        //     stmt.SubStatements.Iter(Visit);     (**)
 4725        //     VisitOneStmt(stmt);                 (***)
 4726        // We may do less for (*), we always use CheckInit instead of Visit in (**), and we do (***) the same.
 04727        if (stmt is AssignStmt) {
 04728          var s = stmt as AssignStmt;
 4729          // The usual visitation of s.SubExpressions.Iter(Visit) would do the following:
 4730          //   Attributes.SubExpressions(s.Attributes).Iter(Visit);  (+)
 4731          //   Visit(s.Lhs);                                         (++)
 4732          //   s.Rhs.SubExpressions.Iter(Visit);                     (+++)
 4733          // Here, we may do less; in particular, we may omit (++).
 04734          Attributes.SubExpressions(s.Attributes).Iter(VisitExpr);  // (+)
 04735          var mse = s.Lhs as MemberSelectExpr;
 04736          if (mse != null && Expression.AsThis(mse.Obj) != null) {
 04737            if (s.Rhs is ExprRhs) {
 4738              // This is a special case we allow.  Omit s.Lhs in the recursive visits.  That is, we omit (++).
 4739              // Furthermore, because the assignment goes to a field of "this" and won't be available until after
 4740              // the "new;", we can allow certain specific (and useful) uses of "this" in the RHS.
 04741              s.Rhs.SubExpressions.Iter(LiberalRHSVisit);  // (+++)
 04742            } else {
 04743              s.Rhs.SubExpressions.Iter(VisitExpr);  // (+++)
 04744            }
 04745          } else {
 04746            VisitExpr(s.Lhs);  // (++)
 04747            s.Rhs.SubExpressions.Iter(VisitExpr);  // (+++)
 04748          }
 04749        } else {
 04750          stmt.SubExpressions.Iter(VisitExpr);  // (*)
 04751        }
 04752        stmt.SubStatements.Iter(CheckInit);  // (**)
 04753        int dummy = 0;
 04754        VisitOneStmt(stmt, ref dummy);  // (***)
 04755      }
 04756      void VisitExpr(Expression expr) {
 4757        Contract.Requires(expr != null);
 04758        Visit(expr, 0);
 04759      }
 04760      protected override bool VisitOneExpr(Expression expr, ref int unused) {
 04761        if (expr is MemberSelectExpr) {
 04762          var e = (MemberSelectExpr)expr;
 04763          if (e.Member.IsInstanceIndependentConstant && Expression.AsThis(e.Obj) != null) {
 04764            return false;  // don't continue the recursion
 4765          }
 04766        } else if (expr is ThisExpr && !(expr is ImplicitThisExpr_ConstructorCall)) {
 04767          resolver.reporter.Error(MessageSource.Resolver, expr.tok, "in the first division of the constructor body (befo
 04768        }
 04769        return base.VisitOneExpr(expr, ref unused);
 04770      }
 04771      void LiberalRHSVisit(Expression expr) {
 4772        Contract.Requires(expr != null);
 4773        // It is important not to allow "this" to flow into something that can be used (for compilation or
 4774        // verification purposes) before the "new;", because, to the verifier, "this" has not yet been allocated.
 4775        // The verifier is told that everything reachable from the heap is expected to be allocated and satisfy all
 4776        // the usual properties, so "this" had better not become reachable from the heap until after the "new;"
 4777        // that does the actual allocation of "this".
 4778        // Within these restrictions, we can allow the (not yet fully available) value "this" to flow into values
 4779        // stored in fields of "this".  Such values are naked occurrences of "this" and "this" occurring
 4780        // as part of constructing a value type.  Since by this rule, "this" may be part of the value stored in
 4781        // a field of "this", we must apply the same rules to uses of the values of fields of "this".
 04782        if (expr is ConcreteSyntaxExpression) {
 04783        } else if (expr is ThisExpr) {
 04784        } else if (expr is MemberSelectExpr && IsThisDotField((MemberSelectExpr)expr)) {
 04785        } else if (expr is SetDisplayExpr) {
 04786        } else if (expr is MultiSetDisplayExpr) {
 04787        } else if (expr is SeqDisplayExpr) {
 04788        } else if (expr is MapDisplayExpr) {
 04789        } else if (expr is BinaryExpr && IsCollectionOperator(((BinaryExpr)expr).ResolvedOp)) {
 04790        } else if (expr is DatatypeValue) {
 04791        } else if (expr is ITEExpr) {
 04792          var e = (ITEExpr)expr;
 04793          VisitExpr(e.Test);
 04794          LiberalRHSVisit(e.Thn);
 04795          LiberalRHSVisit(e.Els);
 04796          return;
 04797        } else {
 4798          // defer to the usual Visit
 04799          VisitExpr(expr);
 04800          return;
 4801        }
 04802        expr.SubExpressions.Iter(LiberalRHSVisit);
 04803      }
 04804      static bool IsThisDotField(MemberSelectExpr expr) {
 4805        Contract.Requires(expr != null);
 04806        return Expression.AsThis(expr.Obj) != null && expr.Member is Field;
 04807      }
 04808      static bool IsCollectionOperator(BinaryExpr.ResolvedOpcode op) {
 04809        switch (op) {
 4810          // sets:  +, *, -
 4811          case BinaryExpr.ResolvedOpcode.Union:
 4812          case BinaryExpr.ResolvedOpcode.Intersection:
 4813          case BinaryExpr.ResolvedOpcode.SetDifference:
 4814          // multisets: +, *, -
 4815          case BinaryExpr.ResolvedOpcode.MultiSetUnion:
 4816          case BinaryExpr.ResolvedOpcode.MultiSetIntersection:
 4817          case BinaryExpr.ResolvedOpcode.MultiSetDifference:
 4818          // sequences: +
 4819          case BinaryExpr.ResolvedOpcode.Concat:
 4820          // maps: +, -
 4821          case BinaryExpr.ResolvedOpcode.MapMerge:
 4822          case BinaryExpr.ResolvedOpcode.MapSubtraction:
 04823            return true;
 4824          default:
 04825            return false;
 4826        }
 04827      }
 4828    }
 4829    #endregion
 4830
 4831    // ------------------------------------------------------------------------------------------------------
 4832    // ------------------------------------------------------------------------------------------------------
 4833    // ------------------------------------------------------------------------------------------------------
 4834
 66824835    bool InferRequiredEqualitySupport(TypeParameter tp, Type type) {
 4836      Contract.Requires(tp != null);
 4837      Contract.Requires(type != null);
 4838
 66824839      type = type.Normalize();  // we only do a .Normalize() here, because we want to keep stop at any type synonym or s
 100544840      if (type is BasicType) {
 66824841      } else if (type is SetType) {
 04842        var st = (SetType)type;
 04843        return st.Arg.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, st.Arg);
 33104844      } else if (type is MultiSetType) {
 04845        var ms = (MultiSetType)type;
 04846        return ms.Arg.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, ms.Arg);
 33204847      } else if (type is MapType) {
 104848        var mt = (MapType)type;
 104849        return mt.Domain.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, mt.Domain) || InferRequiredEqualitySu
 44044850      } else if (type is SeqType) {
 11044851        var sq = (SeqType)type;
 11044852        return InferRequiredEqualitySupport(tp, sq.Arg);
 43924853      } else if (type is UserDefinedType) {
 21964854        var udt = (UserDefinedType)type;
 21964855        List<TypeParameter> formalTypeArgs = udt.ResolvedClass.TypeArgs;
 21964856        Contract.Assert(formalTypeArgs != null);
 21964857        Contract.Assert(formalTypeArgs.Count == udt.TypeArgs.Count);
 21964858        var i = 0;
 75064859        foreach (var argType in udt.TypeArgs) {
 3064860          var formalTypeArg = formalTypeArgs[i];
 3064861          if ((formalTypeArg.SupportsEquality && argType.AsTypeParameter == tp) || InferRequiredEqualitySupport(tp, argT
 04862            return true;
 4863          }
 3064864          i++;
 3064865        }
 21964866        if (udt.ResolvedClass is TypeSynonymDecl) {
 04867          var syn = (TypeSynonymDecl)udt.ResolvedClass;
 04868          if (syn.IsRevealedInScope(Type.GetScope())) {
 04869            return InferRequiredEqualitySupport(tp, syn.RhsWithArgument(udt.TypeArgs));
 4870          }
 04871        }
 21964872      } else {
 04873        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4874      }
 55684875      return false;
 66824876    }
 4877
 4878    TopLevelDeclWithMembers currentClass;
 4879    public Method currentMethod;
 4880    readonly Scope<TypeParameter>/*!*/ allTypeParameters;
 4881    public readonly Scope<IVariable>/*!*/ scope;
 4882    Scope<Statement>/*!*/ enclosingStatementLabels;
 4883    public readonly Scope<Label>/*!*/ DominatingStatementLabels;
 3064884    List<Statement> loopStack = new List<Statement>();  // the enclosing loops (from which it is possible to break out)
 4885
 4886    /// <summary>
 4887    /// Resolves the types along .ParentTraits and fills in .ParentTraitHeads
 4888    /// </summary>
 11094889    void ResolveParentTraitTypes(TopLevelDeclWithMembers cl, Graph<TopLevelDeclWithMembers> parentRelation) {
 4890      Contract.Requires(cl != null);
 4891      Contract.Requires(currentClass == null);
 4892      Contract.Ensures(currentClass == null);
 4893
 11094894      currentClass = cl;
 11094895      allTypeParameters.PushMarker();
 11094896      ResolveTypeParameters(cl.TypeArgs, false, cl);
 33274897      foreach (var tt in cl.ParentTraits) {
 04898        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 04899        ResolveType(cl.tok, tt, new NoContext(cl.EnclosingModuleDefinition), ResolveTypeOptionEnum.DontInfer, null);
 04900        if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 04901          var udt = tt as UserDefinedType;
 04902          if (udt != null && udt.ResolvedClass is NonNullTypeDecl nntd && nntd.ViewAsClass is TraitDecl trait) {
 4903            // disallowing inheritance in multi module case
 04904            bool termination = true;
 04905            if (cl.EnclosingModuleDefinition == trait.EnclosingModuleDefinition || trait.IsObjectTrait || (Attributes.Co
 4906              // all is good (or the user takes responsibility for the lack of termination checking)
 04907              if (!cl.ParentTraitHeads.Contains(trait)) {
 04908                cl.ParentTraitHeads.Add(trait);
 04909                parentRelation.AddEdge(cl, trait);
 04910              }
 04911            } else {
 04912              reporter.Error(MessageSource.Resolver, udt.tok, "{0} '{1}' is in a different module than trait '{2}'. A {0
 04913            }
 04914          } else {
 04915            reporter.Error(MessageSource.Resolver, udt != null ? udt.tok : cl.tok, "a {0} can only extend traits (found 
 04916          }
 04917        }
 04918      }
 11094919      allTypeParameters.PopMarker();
 11094920      currentClass = null;
 11094921    }
 4922
 4923    /// <summary>
 4924    /// This method idempotently fills in .InheritanceInformation, .ParentFormalTypeParametersToActuals, and the
 4925    /// name->MemberDecl table for "cl" and the transitive parent traits of "cl". It also checks that every (transitive)
 4926    /// parent trait is instantiated with the same type parameters
 4927    /// The method assumes that all types along .ParentTraits have been successfully resolved and .ParentTraitHeads been
 4928    /// </summary>
 11094929    void RegisterInheritedMembers(TopLevelDeclWithMembers cl) {
 4930      Contract.Requires(cl != null);
 4931
 11094932      if (cl.ParentTypeInformation != null) {
 04933        return;
 4934      }
 11094935      cl.ParentTypeInformation = new TopLevelDeclWithMembers.InheritanceInformationClass();
 4936
 4937      // populate .ParentTypeInformation and .ParentFormalTypeParametersToActuals for the immediate parent traits
 33274938      foreach (var tt in cl.ParentTraits) {
 04939        var udt = (UserDefinedType)tt;
 04940        var nntd = (NonNullTypeDecl)udt.ResolvedClass;
 04941        var trait = (TraitDecl)nntd.ViewAsClass;
 04942        cl.ParentTypeInformation.Record(trait, udt);
 04943        Contract.Assert(trait.TypeArgs.Count == udt.TypeArgs.Count);
 04944        for (var i = 0; i < trait.TypeArgs.Count; i++) {
 4945          // there may be duplciate parent traits, which haven't been checked for yet, so add mapping only for the first
 04946          if (!cl.ParentFormalTypeParametersToActuals.ContainsKey(trait.TypeArgs[i])) {
 04947            cl.ParentFormalTypeParametersToActuals.Add(trait.TypeArgs[i], udt.TypeArgs[i]);
 04948          }
 04949        }
 04950      }
 4951
 4952      // populate .ParentTypeInformation and .ParentFormalTypeParametersToActuals for the transitive parent traits
 33274953      foreach (var trait in cl.ParentTraitHeads) {
 4954        // make sure the parent trait has been processed; then, incorporate its inheritance information
 04955        RegisterInheritedMembers(trait);
 04956        cl.ParentTypeInformation.Extend(trait, trait.ParentTypeInformation, cl.ParentFormalTypeParametersToActuals);
 04957        foreach (var entry in trait.ParentFormalTypeParametersToActuals) {
 04958          var v = entry.Value.Subst(cl.ParentFormalTypeParametersToActuals);
 04959          if (!cl.ParentFormalTypeParametersToActuals.ContainsKey(entry.Key)) {
 04960            cl.ParentFormalTypeParametersToActuals.Add(entry.Key, v);
 04961          }
 04962        }
 04963      }
 4964
 4965      // Check that every (transitive) parent trait is instantiated with the same type parameters
 33274966      foreach (var group in cl.ParentTypeInformation.GetTypeInstantiationGroups()) {
 04967        Contract.Assert(1 <= group.Count);
 04968        var ty = group[0].Item1;
 04969        for (var i = 1; i < group.Count; i++) {
 04970          if (!group.GetRange(0, i).Exists(pair => pair.Item1.Equals(group[i].Item1))) {
 04971            var via0 = group[0].Item2.Count == 0 ? "" : " (via " + Util.Comma(group[0].Item2, traitDecl => traitDecl.Nam
 04972            var via1 = group[i].Item2.Count == 0 ? "" : " (via " + Util.Comma(group[i].Item2, traitDecl => traitDecl.Nam
 04973            reporter.Error(MessageSource.Resolver, cl.tok,
 04974              "duplicate trait parents with the same head type must also have the same type arguments; got {0}{1} and {2
 04975              ty, via0, group[i].Item1, via1);
 04976          }
 04977        }
 04978      }
 4979
 4980      // Update the name->MemberDecl table for the class. Report an error if the same name refers to more than one membe
 4981      // except when such duplication is purely that one member, say X, is inherited and the other is an override of X.
 11094982      var inheritedMembers = new Dictionary<string, MemberDecl>();
 33274983      foreach (var trait in cl.ParentTraitHeads) {
 04984        foreach (var traitMember in classMembers[trait].Values) {  // TODO: rather than using .Values, it would be nice 
 04985          if (!inheritedMembers.TryGetValue(traitMember.Name, out var prevMember)) {
 4986            // record "traitMember" as an inherited member
 04987            inheritedMembers.Add(traitMember.Name, traitMember);
 04988          } else if (traitMember == prevMember) {
 4989            // same member, inherited two different ways
 04990          } else if (traitMember.Overrides(prevMember)) {
 4991            // we're inheriting "prevMember" and "traitMember" from different parent traits, where "traitMember" is an o
 04992            Contract.Assert(traitMember.EnclosingClass != cl && prevMember.EnclosingClass != cl && traitMember.Enclosing
 4993            // re-map "traitMember.Name" to point to the overriding member
 04994            inheritedMembers[traitMember.Name] = traitMember;
 04995          } else if (prevMember.Overrides(traitMember)) {
 4996            // we're inheriting "prevMember" and "traitMember" from different parent traits, where "prevMember" is an ov
 04997            Contract.Assert(traitMember.EnclosingClass != cl && prevMember.EnclosingClass != cl && traitMember.Enclosing
 4998            // keep the mapping to "prevMember"
 04999          } else {
 5000            // "prevMember" and "traitMember" refer to different members (with the same name)
 05001            reporter.Error(MessageSource.Resolver, cl.tok, "{0} '{1}' inherits a member named '{2}' from both traits '{3
 05002              cl.WhatKind, cl.Name, traitMember.Name, prevMember.EnclosingClass.Name, traitMember.EnclosingClass.Name);
 05003          }
 05004        }
 05005      }
 5006      // Incorporate the inherited members into the name->MemberDecl mapping of "cl"
 11095007      var members = classMembers[cl];
 33275008      foreach (var entry in inheritedMembers) {
 05009        var name = entry.Key;
 05010        var traitMember = entry.Value;
 05011        if (!members.TryGetValue(name, out var clMember)) {
 05012          members.Add(name, traitMember);
 05013        } else {
 05014          Contract.Assert(clMember.EnclosingClass == cl);  // sanity check
 05015          Contract.Assert(clMember.OverriddenMember == null);  // sanity check
 05016          clMember.OverriddenMember = traitMember;
 05017        }
 05018      }
 11095019    }
 5020
 5021    /// <summary>
 5022    /// Assumes type parameters have already been pushed
 5023    /// </summary>
 11095024    void ResolveClassMemberTypes(TopLevelDeclWithMembers cl) {
 5025      Contract.Requires(cl != null);
 5026      Contract.Requires(currentClass == null);
 5027      Contract.Ensures(currentClass == null);
 11095028      currentClass = cl;
 5029
 190205030      foreach (MemberDecl member in cl.Members) {
 52315031        member.EnclosingClass = cl;
 52315032        if (member is Field) {
 05033          if (member is ConstantField) {
 05034            var m = (ConstantField)member;
 05035            ResolveType(member.tok, ((Field)member).Type, m, ResolveTypeOptionEnum.DontInfer, null);
 05036          } else {
 5037            // In the following, we pass in a NoContext, because any cycle formed by a redirecting-type constraints woul
 5038            // dereference the heap, and such constraints are not allowed to dereference the heap so an error will be pr
 5039            // even if we don't detect this cycle.
 05040            ResolveType(member.tok, ((Field)member).Type, new NoContext(cl.EnclosingModuleDefinition), ResolveTypeOption
 05041          }
 52315042        } else if (member is Function) {
 05043          var f = (Function)member;
 05044          var ec = reporter.Count(ErrorLevel.Error);
 05045          allTypeParameters.PushMarker();
 05046          ResolveTypeParameters(f.TypeArgs, true, f);
 05047          ResolveFunctionSignature(f);
 05048          allTypeParameters.PopMarker();
 05049          if (f is ExtremePredicate && ec == reporter.Count(ErrorLevel.Error)) {
 05050            var ff = ((ExtremePredicate)f).PrefixPredicate;  // note, may be null if there was an error before the prefi
 05051            if (ff != null) {
 05052              ff.EnclosingClass = cl;
 05053              allTypeParameters.PushMarker();
 05054              ResolveTypeParameters(ff.TypeArgs, true, ff);
 05055              ResolveFunctionSignature(ff);
 05056              allTypeParameters.PopMarker();
 05057            }
 05058          }
 05059          if (f.ByMethodDecl != null) {
 05060            f.ByMethodDecl.EnclosingClass = cl;
 05061          }
 5062
 104625063        } else if (member is Method) {
 52315064          var m = (Method)member;
 52315065          var ec = reporter.Count(ErrorLevel.Error);
 52315066          allTypeParameters.PushMarker();
 52315067          ResolveTypeParameters(m.TypeArgs, true, m);
 52315068          ResolveMethodSignature(m);
 52315069          allTypeParameters.PopMarker();
 52315070          if (m is ExtremeLemma com && com.PrefixLemma != null && ec == reporter.Count(ErrorLevel.Error)) {
 05071            var mm = com.PrefixLemma;
 5072            // resolve signature of the prefix lemma
 05073            mm.EnclosingClass = cl;
 05074            allTypeParameters.PushMarker();
 05075            ResolveTypeParameters(mm.TypeArgs, true, mm);
 05076            ResolveMethodSignature(mm);
 05077            allTypeParameters.PopMarker();
 05078          }
 5079
 52315080        } else {
 05081          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected member type
 5082        }
 52315083      }
 5084
 11095085      currentClass = null;
 11095086    }
 5087
 5088    /// <summary>
 5089    /// This method checks the rules for inherited and overridden members. It also populates .InheritedMembers with the
 5090    /// non-static members that are inherited from parent traits.
 5091    /// </summary>
 11095092    void InheritedTraitMembers(TopLevelDeclWithMembers cl) {
 5093      Contract.Requires(cl != null);
 5094      Contract.Requires(cl.ParentTypeInformation != null);
 5095
 245165096      foreach (var member in classMembers[cl].Values) {
 70635097        if (member is PrefixPredicate || member is PrefixLemma) {
 5098          // these are handled with the corresponding extreme predicate/lemma
 05099          continue;
 5100        }
 70635101        if (member.EnclosingClass != cl) {
 5102          // The member is the one inherited from a trait (and the class does not itself define a member with this name)
 5103          // is fine for fields and for functions and methods with bodies. However, if "cl" is not itself a trait, then 
 5104          // or method, "cl" is required to at least redeclare the member with its signature.  (It should also provide a
 5105          // but that will be checked by the verifier.  And it should also have a body, but that will be checked by the 
 05106          if (member.IsStatic) {
 5107            // nothing to do
 05108          } else {
 05109            cl.InheritedMembers.Add(member);
 05110            if (member is Field || (member as Function)?.Body != null || (member as Method)?.Body != null) {
 5111              // member is a field or a fully defined function or method
 05112            } else if (cl is TraitDecl) {
 5113              // there are no expectations that a field needs to repeat the signature of inherited body-less members
 05114            } else if (Attributes.Contains(member.Attributes, "extern")) {
 5115              // Extern functions do not need to be reimplemented.
 5116              // TODO: When `:extern` is separated from `:compile false`, this should become `:compile false`.
 05117            } else if (member is Lemma && Attributes.Contains(member.Attributes, "opaque_reveal")) {
 5118              // reveal lemmas do not need to be reimplemented
 05119            } else {
 05120              reporter.Error(MessageSource.Resolver, cl.tok, "{0} '{1}' does not implement trait {2} '{3}.{4}'", cl.What
 05121            }
 05122          }
 05123          continue;
 5124        }
 141265125        if (member.OverriddenMember == null) {
 5126          // this member has nothing to do with the parent traits
 70635127          continue;
 5128        }
 5129
 05130        var traitMember = member.OverriddenMember;
 05131        var trait = traitMember.EnclosingClass;
 05132        if (traitMember.IsStatic) {
 05133          reporter.Error(MessageSource.Resolver, member.tok, "static {0} '{1}' is inherited from trait '{2}' and is not 
 05134            traitMember.WhatKind, traitMember.Name, trait.Name);
 05135        } else if (member.IsStatic) {
 05136          reporter.Error(MessageSource.Resolver, member.tok, "static member '{0}' overrides non-static member in trait '
 05137        } else if (traitMember is Field) {
 5138          // The class is not allowed to do anything with the field other than silently inherit it.
 05139          reporter.Error(MessageSource.Resolver, member.tok, "{0} '{1}' is inherited from trait '{2}' and is not allowed
 05140        } else if ((traitMember as Function)?.Body != null || (traitMember as Method)?.Body != null) {
 5141          // the overridden member is a fully defined function or method, so the class is not allowed to do anything wit
 05142          reporter.Error(MessageSource.Resolver, member.tok, "fully defined {0} '{1}' is inherited from trait '{2}' and 
 05143            traitMember.WhatKind, traitMember.Name, trait.Name);
 05144        } else if (member is Method != traitMember is Method ||
 05145                   member is Lemma != traitMember is Lemma ||
 05146                   member is TwoStateLemma != traitMember is TwoStateLemma ||
 05147                   member is LeastLemma != traitMember is LeastLemma ||
 05148                   member is GreatestLemma != traitMember is GreatestLemma ||
 05149                   member is Function != traitMember is Function ||
 05150                   member is TwoStateFunction != traitMember is TwoStateFunction ||
 05151                   member is LeastPredicate != traitMember is LeastPredicate ||
 05152                   member is GreatestPredicate != traitMember is GreatestPredicate) {
 05153          reporter.Error(MessageSource.Resolver, member.tok, "{0} '{1}' in '{2}' can only be overridden by a {0} (got {3
 05154        } else if (member.IsGhost != traitMember.IsGhost) {
 05155          reporter.Error(MessageSource.Resolver, member.tok, "overridden {0} '{1}' in '{2}' has different ghost/compiled
 05156            traitMember.WhatKind, traitMember.Name, cl.Name, trait.Name);
 05157        } else {
 5158          // Copy trait member's extern attribute onto class member if class does not provide one
 05159          if (!Attributes.Contains(member.Attributes, "extern") && Attributes.Contains(traitMember.Attributes, "extern")
 05160            var traitExternArgs = Attributes.FindExpressions(traitMember.Attributes, "extern");
 05161            member.Attributes = new Attributes("extern", traitExternArgs, member.Attributes);
 05162          }
 5163
 05164          if (traitMember is Method) {
 05165            var classMethod = (Method)member;
 05166            var traitMethod = (Method)traitMember;
 05167            classMethod.OverriddenMethod = traitMethod;
 5168
 05169            CheckOverride_MethodParameters(classMethod, traitMethod, cl.ParentFormalTypeParametersToActuals);
 5170
 05171            var traitMethodAllowsNonTermination = Contract.Exists(traitMethod.Decreases.Expressions, e => e is WildcardE
 05172            var classMethodAllowsNonTermination = Contract.Exists(classMethod.Decreases.Expressions, e => e is WildcardE
 05173            if (classMethodAllowsNonTermination && !traitMethodAllowsNonTermination) {
 05174              reporter.Error(MessageSource.Resolver, classMethod.tok, "not allowed to override a terminating method with
 05175            }
 5176
 05177          } else if (traitMember is Function) {
 05178            var classFunction = (Function)member;
 05179            var traitFunction = (Function)traitMember;
 05180            classFunction.OverriddenFunction = traitFunction;
 5181
 05182            CheckOverride_FunctionParameters(classFunction, traitFunction, cl.ParentFormalTypeParametersToActuals);
 5183
 05184          } else {
 05185            Contract.Assert(false); // unexpected member
 05186          }
 05187        }
 05188      }
 11095189    }
 5190
 05191    public void CheckOverride_FunctionParameters(Function nw, Function old, Dictionary<TypeParameter, Type> classTypeMap
 5192      Contract.Requires(nw != null);
 5193      Contract.Requires(old != null);
 5194      Contract.Requires(classTypeMap != null);
 5195
 05196      var typeMap = CheckOverride_TypeParameters(nw.tok, old.TypeArgs, nw.TypeArgs, nw.Name, "function", classTypeMap);
 05197      if (nw is ExtremePredicate nwFix && old is ExtremePredicate oldFix && nwFix.KNat != oldFix.KNat) {
 05198        reporter.Error(MessageSource.Resolver, nw,
 05199          "the type of special parameter '_k' of {0} '{1}' ({2}) must be the same as in the overridden {0} ({3})",
 05200          nw.WhatKind, nw.Name, nwFix.KNat ? "nat" : "ORDINAL", oldFix.KNat ? "nat" : "ORDINAL");
 05201      }
 05202      CheckOverride_ResolvedParameters(nw.tok, old.Formals, nw.Formals, nw.Name, "function", "parameter", typeMap);
 05203      var oldResultType = old.ResultType.Subst(typeMap);
 05204      if (!nw.ResultType.Equals(oldResultType, true)) {
 05205        reporter.Error(MessageSource.Resolver, nw, "the result type of function '{0}' ({1}) differs from that in the ove
 05206          nw.Name, nw.ResultType, oldResultType);
 05207      }
 05208    }
 5209
 05210    public void CheckOverride_MethodParameters(Method nw, Method old, Dictionary<TypeParameter, Type> classTypeMap) {
 5211      Contract.Requires(nw != null);
 5212      Contract.Requires(old != null);
 5213      Contract.Requires(classTypeMap != null);
 05214      var typeMap = CheckOverride_TypeParameters(nw.tok, old.TypeArgs, nw.TypeArgs, nw.Name, "method", classTypeMap);
 05215      if (nw is ExtremeLemma nwFix && old is ExtremeLemma oldFix && nwFix.KNat != oldFix.KNat) {
 05216        reporter.Error(MessageSource.Resolver, nw,
 05217          "the type of special parameter '_k' of {0} '{1}' ({2}) must be the same as in the overridden {0} ({3})",
 05218          nw.WhatKind, nw.Name, nwFix.KNat ? "nat" : "ORDINAL", oldFix.KNat ? "nat" : "ORDINAL");
 05219      }
 05220      CheckOverride_ResolvedParameters(nw.tok, old.Ins, nw.Ins, nw.Name, "method", "in-parameter", typeMap);
 05221      CheckOverride_ResolvedParameters(nw.tok, old.Outs, nw.Outs, nw.Name, "method", "out-parameter", typeMap);
 05222    }
 5223
 05224    private Dictionary<TypeParameter, Type> CheckOverride_TypeParameters(IToken tok, List<TypeParameter> old, List<TypeP
 5225      Contract.Requires(tok != null);
 5226      Contract.Requires(old != null);
 5227      Contract.Requires(nw != null);
 5228      Contract.Requires(name != null);
 5229      Contract.Requires(thing != null);
 05230      var typeMap = old.Count == 0 ? classTypeMap : new Dictionary<TypeParameter, Type>(classTypeMap);
 05231      if (old.Count != nw.Count) {
 05232        reporter.Error(MessageSource.Resolver, tok,
 05233          "{0} '{1}' is declared with a different number of type parameters ({2} instead of {3}) than in the overridden 
 05234      } else {
 05235        for (int i = 0; i < old.Count; i++) {
 05236          var o = old[i];
 05237          var n = nw[i];
 05238          typeMap.Add(o, new UserDefinedType(tok, n));
 5239          // Check type characteristics
 05240          if (o.Characteristics.EqualitySupport != TypeParameter.EqualitySupportValue.InferredRequired && o.Characterist
 05241            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05242          }
 05243          if (o.Characteristics.HasCompiledValue != n.Characteristics.HasCompiledValue) {
 05244            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05245          } else if (o.Characteristics.IsNonempty != n.Characteristics.IsNonempty) {
 05246            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05247          }
 05248          if (o.Characteristics.ContainsNoReferenceTypes != n.Characteristics.ContainsNoReferenceTypes) {
 05249            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the no-referenc
 05250          }
 5251
 05252        }
 05253      }
 05254      return typeMap;
 05255    }
 5256
 05257    private void CheckOverride_ResolvedParameters(IToken tok, List<Formal> old, List<Formal> nw, string name, string thi
 5258      Contract.Requires(tok != null);
 5259      Contract.Requires(old != null);
 5260      Contract.Requires(nw != null);
 5261      Contract.Requires(name != null);
 5262      Contract.Requires(thing != null);
 5263      Contract.Requires(parameterKind != null);
 5264      Contract.Requires(typeMap != null);
 05265      if (old.Count != nw.Count) {
 05266        reporter.Error(MessageSource.Resolver, tok, "{0} '{1}' is declared with a different number of {2} ({3} instead o
 05267          thing, name, parameterKind, nw.Count, old.Count);
 05268      } else {
 05269        for (int i = 0; i < old.Count; i++) {
 05270          var o = old[i];
 05271          var n = nw[i];
 05272          if (!o.IsGhost && n.IsGhost) {
 05273            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05274              parameterKind, n.Name, thing, name);
 05275          } else if (o.IsGhost && !n.IsGhost) {
 05276            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05277              parameterKind, n.Name, thing, name);
 05278          } else if (!o.IsOld && n.IsOld) {
 05279            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05280              parameterKind, n.Name, thing, name);
 05281          } else if (o.IsOld && !n.IsOld) {
 05282            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05283              parameterKind, n.Name, thing, name);
 05284          } else if (!o.IsOlder && n.IsOlder) {
 05285            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05286              parameterKind, n.Name, thing, name);
 05287          } else if (o.IsOlder && !n.IsOlder) {
 05288            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05289              parameterKind, n.Name, thing, name);
 05290          } else {
 05291            var oo = o.Type.Subst(typeMap);
 05292            if (!n.Type.Equals(oo, true)) {
 05293              reporter.Error(MessageSource.Resolver, n.tok,
 05294                "the type of {0} '{1}' is different from the type of the corresponding {0} in trait {2} ('{3}' instead o
 05295                parameterKind, n.Name, thing, n.Type, oo);
 05296            }
 05297          }
 05298        }
 05299      }
 05300    }
 5301
 5302    /// <summary>
 5303    /// Check that the SCC of 'startingPoint' can be carved up into stratospheres in such a way that each
 5304    /// datatype has some value that can be constructed from datatypes in lower stratospheres only.
 5305    /// The algorithm used here is quadratic in the number of datatypes in the SCC.  Since that number is
 5306    /// deemed to be rather small, this seems okay.
 5307    ///
 5308    /// As a side effect of this checking, the GroundingCtor field is filled in (for every inductive datatype
 5309    /// that passes the check).  It may be that several constructors could be used as the default, but
 5310    /// only the first one encountered as recorded.  This particular choice is slightly more than an
 5311    /// implementation detail, because it affects how certain cycles among inductive datatypes (having
 5312    /// to do with the types used to instantiate type parameters of datatypes) are used.
 5313    ///
 5314    /// The role of the SCC here is simply to speed up this method.  It would still be correct if the
 5315    /// equivalence classes in the given SCC were unions of actual SCC's.  In particular, this method
 5316    /// would still work if "dependencies" consisted of one large SCC containing all the inductive
 5317    /// datatypes in the module.
 5318    /// </summary>
 5275319    void SccStratosphereCheck(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
 5320      Contract.Requires(startingPoint != null);
 5321      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 5322
 5275323      var scc = dependencies.GetSCC(startingPoint);
 5275324      int totalCleared = 0;
 10545325      while (true) {
 5275326        int clearedThisRound = 0;
 31625327        foreach (var dt in scc) {
 5275328          if (dt.GroundingCtor != null) {
 5329            // previously cleared
 10545330          } else if (ComputeGroundingCtor(dt)) {
 5275331            Contract.Assert(dt.GroundingCtor != null);  // should have been set by the successful call to StratosphereCh
 5275332            clearedThisRound++;
 5275333            totalCleared++;
 5275334          }
 5275335        }
 10545336        if (totalCleared == scc.Count) {
 5337          // all is good
 5275338          return;
 05339        } else if (clearedThisRound != 0) {
 5340          // some progress was made, so let's keep going
 05341        } else {
 5342          // whatever is in scc-cleared now failed to pass the test
 05343          foreach (var dt in scc) {
 05344            if (dt.GroundingCtor == null) {
 05345              reporter.Error(MessageSource.Resolver, dt, "because of cyclic dependencies among constructor argument type
 05346            }
 05347          }
 05348          return;
 5349        }
 05350      }
 5275351    }
 5352
 5353    /// <summary>
 5354    /// Check that the datatype has some constructor all whose argument types can be constructed.
 5355    /// Returns 'true' and sets dt.GroundingCtor if that is the case.
 5356    /// </summary>
 5275357    bool ComputeGroundingCtor(IndDatatypeDecl dt) {
 5358      Contract.Requires(dt != null);
 5359      Contract.Requires(dt.GroundingCtor == null);  // the intention is that this method be called only when GroundingCt
 5360      Contract.Ensures(!Contract.Result<bool>() || dt.GroundingCtor != null);
 5361
 5362      // Stated differently, check that there is some constuctor where no argument type goes to the same stratum.
 5275363      DatatypeCtor groundingCtor = null;
 5275364      ISet<TypeParameter> lastTypeParametersUsed = null;
 46175365      foreach (DatatypeCtor ctor in dt.Ctors) {
 10125366        var typeParametersUsed = new HashSet<TypeParameter>();
 54965367        foreach (Formal p in ctor.Formals) {
 8205368          if (!CheckCanBeConstructed(p.Type, typeParametersUsed)) {
 5369            // the argument type (has a component which) is not yet known to be constructable
 05370            goto NEXT_OUTER_ITERATION;
 5371          }
 8205372        }
 5373        // this constructor satisfies the requirements, check to see if it is a better fit than the
 5374        // one found so far. Here, "better" means
 5375        //   * a ghost constructor is better than a non-ghost constructor
 5376        //   * among those, a constructor with fewer type arguments is better
 5377        //   * among those, the first one is preferred.
 15395378        if (groundingCtor == null || (!groundingCtor.IsGhost && ctor.IsGhost) || typeParametersUsed.Count < lastTypePara
 5275379          groundingCtor = ctor;
 5275380          lastTypeParametersUsed = typeParametersUsed;
 5275381        }
 5382
 30365383      NEXT_OUTER_ITERATION: { }
 10125384      }
 5385
 10545386      if (groundingCtor != null) {
 5275387        dt.GroundingCtor = groundingCtor;
 5275388        dt.TypeParametersUsedInConstructionByGroundingCtor = new bool[dt.TypeArgs.Count];
 26655389        for (int i = 0; i < dt.TypeArgs.Count; i++) {
 5375390          dt.TypeParametersUsedInConstructionByGroundingCtor[i] = lastTypeParametersUsed.Contains(dt.TypeArgs[i]);
 5375391        }
 5275392        return true;
 5393      }
 5394
 5395      // no constructor satisfied the requirements, so this is an illegal datatype declaration
 05396      return false;
 5275397    }
 5398
 9005399    bool CheckCanBeConstructed(Type type, ISet<TypeParameter> typeParametersUsed) {
 9005400      type = type.NormalizeExpandKeepConstraints();
 13105401      if (type is BasicType) {
 5402        // values of primitive types can always be constructed
 4105403        return true;
 5555404      } else if (type is CollectionType) {
 5405        // values of collection types can always be constructed
 655406        return true;
 5407      }
 5408
 4255409      var udt = (UserDefinedType)type;
 4255410      var cl = udt.ResolvedClass;
 4255411      Contract.Assert(cl != null);
 8005412      if (cl is TypeParameter) {
 5413        // treat a type parameter like a ground type
 3755414        typeParametersUsed.Add((TypeParameter)cl);
 3755415        return true;
 505416      } else if (cl is AbstractTypeDecl) {
 5417        // an opaque is like a ground type
 05418        return true;
 505419      } else if (cl is InternalTypeSynonymDecl) {
 5420        // a type exported as opaque from another module is like a ground type
 05421        return true;
 505422      } else if (cl is NewtypeDecl) {
 5423        // values of a newtype can be constructed
 05424        return true;
 605425      } else if (cl is SubsetTypeDecl) {
 105426        var td = (SubsetTypeDecl)cl;
 105427        if (td.Witness != null) {
 5428          // a witness exists, but may depend on type parameters
 05429          type.AddFreeTypeParameters(typeParametersUsed);
 05430          return true;
 205431        } else if (td.WitnessKind == SubsetTypeDecl.WKind.Special) {
 5432          // WKind.Special is only used with -->, ->, and non-null types:
 105433          Contract.Assert(ArrowType.IsPartialArrowTypeName(td.Name) || ArrowType.IsTotalArrowTypeName(td.Name) || td is 
 105434          if (ArrowType.IsTotalArrowTypeName(td.Name)) {
 05435            return CheckCanBeConstructed(udt.TypeArgs.Last(), typeParametersUsed);
 105436          } else {
 105437            return true;
 5438          }
 05439        } else {
 05440          return CheckCanBeConstructed(td.RhsWithArgument(udt.TypeArgs), typeParametersUsed);
 5441        }
 405442      } else if (cl is ClassDecl) {
 5443        // null is a value for this possibly-null type
 05444        return true;
 405445      } else if (cl is CoDatatypeDecl) {
 5446        // may depend on type parameters
 05447        type.AddFreeTypeParameters(typeParametersUsed);
 05448        return true;
 5449      }
 5450
 405451      var dependee = type.AsIndDatatype;
 405452      Contract.Assert(dependee != null);
 405453      if (dependee.GroundingCtor == null) {
 5454        // the type is an inductive datatype that we don't yet know how to construct
 05455        return false;
 5456      }
 5457      // also check the type arguments of the inductive datatype
 405458      Contract.Assert(udt.TypeArgs.Count == dependee.TypeParametersUsedInConstructionByGroundingCtor.Length);
 405459      var i = 0;
 4205460      foreach (var ta in udt.TypeArgs) {
 1005461        if (dependee.TypeParametersUsedInConstructionByGroundingCtor[i] && !CheckCanBeConstructed(ta, typeParametersUsed
 05462          return false;
 5463        }
 1005464        i++;
 1005465      }
 405466      return true;
 9005467    }
 5468
 5275469    void DetermineEqualitySupport(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
 5470      Contract.Requires(startingPoint != null);
 5471      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 5472
 5275473      var scc = dependencies.GetSCC(startingPoint);
 5474
 05475      void MarkSCCAsNotSupportingEquality() {
 05476        foreach (var ddtt in scc) {
 05477          ddtt.EqualitySupport = IndDatatypeDecl.ES.Never;
 05478        }
 05479      }
 5480
 5481      // Look for conditions that make the whole SCC incapable of providing the equality operation:
 5482      //   * a datatype in the SCC has a ghost constructor
 5483      //   * a parameter of an inductive datatype in the SCC is ghost
 5484      //   * the type of a parameter of an inductive datatype in the SCC does not support equality
 31625485      foreach (var dt in scc) {
 5275486        Contract.Assume(dt.EqualitySupport == IndDatatypeDecl.ES.NotYetComputed);
 46175487        foreach (var ctor in dt.Ctors) {
 10125488          if (ctor.IsGhost) {
 05489            MarkSCCAsNotSupportingEquality();
 05490            return;  // we are done
 5491          }
 54965492          foreach (var arg in ctor.Formals) {
 8205493            var anotherIndDt = arg.Type.AsIndDatatype;
 8205494            if (arg.IsGhost ||
 8205495                (anotherIndDt != null && anotherIndDt.EqualitySupport == IndDatatypeDecl.ES.Never) ||
 8205496                arg.Type.IsCoDatatype ||
 8205497                arg.Type.IsArrowType) {
 5498              // arg.Type is known never to support equality
 05499              MarkSCCAsNotSupportingEquality();
 05500              return;  // we are done
 5501            }
 8205502          }
 10125503        }
 5275504      }
 5505
 5506      // Now for the more involved case:  we need to determine which type parameters determine equality support for each
 5507      // We start by seeing where each datatype's type parameters are used in a place known to determine equality suppor
 5275508      bool thingsChanged = false;
 31625509      foreach (var dt in scc) {
 6925510        if (dt.TypeArgs.Count == 0) {
 5511          // if the datatype has no type parameters, we certainly won't find any type parameters being used in the argum
 1655512          continue;
 5513        }
 30725514        foreach (var ctor in dt.Ctors) {
 32315515          foreach (var arg in ctor.Formals) {
 4155516            var typeArg = arg.Type.AsTypeParameter;
 7905517            if (typeArg != null) {
 3755518              typeArg.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 3755519              thingsChanged = true;
 4155520            } else {
 405521              var otherDt = arg.Type.AsIndDatatype;
 405522              if (otherDt != null && otherDt.EqualitySupport == IndDatatypeDecl.ES.ConsultTypeArguments) {  // datatype 
 05523                var otherUdt = (UserDefinedType)arg.Type.NormalizeExpand();
 05524                var i = 0;
 05525                foreach (var otherTp in otherDt.TypeArgs) {
 05526                  if (otherTp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05527                    var tp = otherUdt.TypeArgs[i].AsTypeParameter;
 05528                    if (tp != null) {
 05529                      tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05530                      thingsChanged = true;
 05531                    }
 05532                  }
 05533                }
 05534              }
 405535            }
 4155536          }
 6625537        }
 3625538      }
 5539      // Then we propagate this information up through the SCC
 8175540      while (thingsChanged) {
 1455541        thingsChanged = false;
 8705542        foreach (var dt in scc) {
 1455543          if (dt.TypeArgs.Count == 0) {
 5544            // if the datatype has no type parameters, we certainly won't find any type parameters being used in the arg
 05545            continue;
 5546          }
 15005547          foreach (var ctor in dt.Ctors) {
 22805548            foreach (var arg in ctor.Formals) {
 4055549              var otherDt = arg.Type.AsIndDatatype;
 4055550              if (otherDt != null && otherDt.EqualitySupport == IndDatatypeDecl.ES.NotYetComputed) { // otherDt lives in
 05551                var otherUdt = (UserDefinedType)arg.Type.NormalizeExpand();
 05552                var i = 0;
 05553                foreach (var otherTp in otherDt.TypeArgs) {
 05554                  if (otherTp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05555                    var tp = otherUdt.TypeArgs[i].AsTypeParameter;
 05556                    if (tp != null && !tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05557                      tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05558                      thingsChanged = true;
 05559                    }
 05560                  }
 05561                  i++;
 05562                }
 05563              }
 4055564            }
 3555565          }
 1455566        }
 1455567      }
 5568      // Now that we have computed the .NecessaryForEqualitySupportOfSurroundingInductiveDatatype values, mark the datat
 5569      // where equality support should be checked by looking at the type arguments.
 31625570      foreach (var dt in scc) {
 5275571        dt.EqualitySupport = IndDatatypeDecl.ES.ConsultTypeArguments;
 5275572      }
 5275573    }
 5574
 5575    /// <summary>
 5576    /// Check to see if the attribute is one that is supported by Dafny.  What check performed here is,
 5577    /// unfortunately, just an approximation, since the usage rules of a particular attribute is checked
 5578    /// elsewhere (for example, in the compiler or verifier).  It would be nice to improve this.
 5579    /// </summary>
 05580    bool IsRecognizedAttribute(UserSuppliedAttributes a, IAttributeBearingDeclaration host) {
 5581      Contract.Requires(a != null);
 5582      Contract.Requires(host != null);
 05583      switch (a.Name) {
 5584        case "opaque":
 05585          return host is Function && !(host is ExtremePredicate);
 5586        case "trigger":
 05587          return host is ComprehensionExpr || host is SetComprehension || host is MapComprehension;
 5588        case "timeLimit":
 5589        case "timeLimitMultiplier":
 05590          return host is TopLevelDecl;
 5591        case "tailrecursive":
 05592          return host is Method && !((Method)host).IsGhost;
 5593        case "autocontracts":
 05594          return host is ClassDecl;
 5595        case "autoreq":
 05596          return host is Function;
 5597        case "abstemious":
 05598          return host is Function;
 5599        case "options":
 05600          return host is ModuleDefinition;
 5601        default:
 05602          return false;
 5603      }
 05604    }
 5605
 1224525606    public void ScopePushAndReport(Scope<IVariable> scope, IVariable v, string kind) {
 5607      Contract.Requires(scope != null);
 5608      Contract.Requires(v != null);
 5609      Contract.Requires(kind != null);
 1224525610      ScopePushAndReport(scope, v.Name, v, v.Tok, kind);
 1224525611    }
 5612
 1224525613    void ScopePushAndReport<Thing>(Scope<Thing> scope, string name, Thing thing, IToken tok, string kind) where Thing : 
 5614      Contract.Requires(scope != null);
 5615      Contract.Requires(name != null);
 5616      Contract.Requires(thing != null);
 5617      Contract.Requires(tok != null);
 5618      Contract.Requires(kind != null);
 1224525619      var r = scope.Push(name, thing);
 1224525620      switch (r) {
 5621        case Scope<Thing>.PushResult.Success:
 1224525622          break;
 5623        case Scope<Thing>.PushResult.Duplicate:
 05624          reporter.Error(MessageSource.Resolver, ErrorRegistry.NoneId, tok, "Duplicate {0} name: {1}", kind, name);
 05625          break;
 5626        case Scope<Thing>.PushResult.Shadow:
 05627          reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, tok, "Shadowed {0} name: {1}", kind, name);
 05628          break;
 5629      }
 1224525630    }
 5631
 5632    /// <summary>
 5633    /// Assumes type parameters have already been pushed
 5634    /// </summary>
 6125635    void ResolveFunctionSignature(Function f) {
 5636      Contract.Requires(f != null);
 6125637      scope.PushMarker();
 6125638      if (f.SignatureIsOmitted) {
 05639        reporter.Error(MessageSource.Resolver, f, "function signature can be omitted only in refining functions");
 05640      }
 6125641      var option = f.TypeArgs.Count == 0 ? new ResolveTypeOption(f) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowP
 36725642      foreach (Formal p in f.Formals) {
 6125643        ScopePushAndReport(scope, p, "parameter");
 6125644        ResolveType(p.tok, p.Type, f, option, f.TypeArgs);
 6125645      }
 6125646      if (f.Result != null) {
 05647        ScopePushAndReport(scope, f.Result, "parameter/return");
 05648        ResolveType(f.Result.tok, f.Result.Type, f, option, f.TypeArgs);
 6125649      } else {
 6125650        ResolveType(f.tok, f.ResultType, f, option, f.TypeArgs);
 6125651      }
 6125652      scope.PopMarker();
 6125653    }
 5654
 5655    /// <summary>
 5656    /// This method can be called even if the resolution of "fe" failed; in that case, this method will
 5657    /// not issue any error message.
 5658    /// </summary>
 05659    public void DisallowNonGhostFieldSpecifiers(FrameExpression fe) {
 5660      Contract.Requires(fe != null);
 05661      if (fe.Field != null && !fe.Field.IsGhost) {
 05662        reporter.Error(MessageSource.Resolver, fe.E, "in a ghost context, only ghost fields can be mentioned as modifies
 05663      }
 05664    }
 5665
 5666    /// <summary>
 5667    /// Assumes type parameters have already been pushed
 5668    /// </summary>
 52315669    void ResolveMethodSignature(Method m) {
 5670      Contract.Requires(m != null);
 5671
 52315672      scope.PushMarker();
 52315673      if (m.SignatureIsOmitted) {
 05674        reporter.Error(MessageSource.Resolver, m, "method signature can be omitted only in refining methods");
 05675      }
 52315676      var option = m.TypeArgs.Count == 0 ? new ResolveTypeOption(m) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowP
 5677      // resolve in-parameters
 483905678      foreach (Formal p in m.Ins) {
 108995679        ScopePushAndReport(scope, p, "parameter");
 108995680        ResolveType(p.tok, p.Type, m, option, m.TypeArgs);
 108995681      }
 5682      // resolve out-parameters
 337895683      foreach (Formal p in m.Outs) {
 60325684        ScopePushAndReport(scope, p, "parameter");
 60325685        ResolveType(p.tok, p.Type, m, option, m.TypeArgs);
 60325686      }
 52315687      scope.PopMarker();
 52315688    }
 5689
 5690    /// <summary>
 5691    /// Assumes type parameters have already been pushed
 5692    /// </summary>
 05693    void ResolveIteratorSignature(IteratorDecl iter) {
 5694      Contract.Requires(iter != null);
 05695      scope.PushMarker();
 05696      if (iter.SignatureIsOmitted) {
 05697        reporter.Error(MessageSource.Resolver, iter, "iterator signature can be omitted only in refining methods");
 05698      }
 05699      var initiallyNoTypeArguments = iter.TypeArgs.Count == 0;
 05700      var option = initiallyNoTypeArguments ? new ResolveTypeOption(iter) : new ResolveTypeOption(ResolveTypeOptionEnum.
 5701      // resolve the types of the parameters
 05702      var prevErrorCount = reporter.Count(ErrorLevel.Error);
 05703      foreach (var p in iter.Ins) {
 05704        ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05705      }
 05706      foreach (var p in iter.Outs) {
 05707        ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05708        if (!p.Type.KnownToHaveToAValue(p.IsGhost)) {
 05709          reporter.Error(MessageSource.Resolver, p.tok, "type of yield-parameter must support auto-initialization (got '
 05710        }
 05711      }
 5712      // resolve the types of the added fields (in case some of these types would cause the addition of default type arg
 05713      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 05714        foreach (var p in iter.OutsHistoryFields) {
 05715          ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05716        }
 05717      }
 05718      if (iter.TypeArgs.Count != iter.NonNullTypeDecl.TypeArgs.Count) {
 5719        // Apparently, the type resolution automatically added type arguments to the iterator. We'll add these to the
 5720        // corresponding non-null type as well.
 05721        Contract.Assert(initiallyNoTypeArguments);
 05722        Contract.Assert(iter.NonNullTypeDecl.TypeArgs.Count == 0);
 05723        var nnt = iter.NonNullTypeDecl;
 05724        nnt.TypeArgs.AddRange(iter.TypeArgs.ConvertAll(tp => new TypeParameter(tp.RangeToken, tp.NameNode, tp.VarianceSy
 05725        var varUdt = (UserDefinedType)nnt.Var.Type;
 05726        Contract.Assert(varUdt.TypeArgs.Count == 0);
 05727        varUdt.TypeArgs = nnt.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp));
 05728      }
 05729      scope.PopMarker();
 05730    }
 5731
 5732    // Like the ResolveTypeOptionEnum, but iff the case of AllowPrefixExtend, it also
 5733    // contains a pointer to its Parent class, to fill in default type parameters properly.
 5734    public class ResolveTypeOption {
 5735      public readonly ResolveTypeOptionEnum Opt;
 5736      public readonly TypeParameter.ParentType Parent;
 5737      [ContractInvariantMethod]
 05738      void ObjectInvariant() {
 5739        Contract.Invariant((Opt == ResolveTypeOptionEnum.AllowPrefixExtend) == (Parent != null));
 05740      }
 5741
 5716425742      public ResolveTypeOption(ResolveTypeOptionEnum opt) {
 5743        Contract.Requires(opt != ResolveTypeOptionEnum.AllowPrefixExtend);
 2858215744        Parent = null;
 2858215745        Opt = opt;
 2858215746      }
 5747
 105825748      public ResolveTypeOption(TypeParameter.ParentType parent) {
 5749        Contract.Requires(parent != null);
 52915750        Opt = ResolveTypeOptionEnum.AllowPrefixExtend;
 52915751        Parent = parent;
 52915752      }
 5753    }
 5754
 5755    /// <summary>
 5756    /// Returns a resolved type denoting an array type with dimension "dims" and element type "arg".
 5757    /// Callers are expected to provide "arg" as an already resolved type.  (Note, a proxy type is resolved--
 5758    /// only types that contain identifiers stand the possibility of not being resolved.)
 5759    /// </summary>
 91955760    Type ResolvedArrayType(IToken tok, int dims, Type arg, ResolutionContext resolutionContext, bool useClassNameType) {
 5761      Contract.Requires(tok != null);
 5762      Contract.Requires(1 <= dims);
 5763      Contract.Requires(arg != null);
 91955764      var at = builtIns.ArrayType(tok, dims, new List<Type> { arg }, false, useClassNameType);
 91955765      ResolveType(tok, at, resolutionContext, ResolveTypeOptionEnum.DontInfer, null);
 91955766      return at;
 91955767    }
 5768
 3055769    void FillInDefaultLoopDecreases(LoopStmt loopStmt, Expression guard, List<Expression> theDecreases, ICallable enclos
 5770      Contract.Requires(loopStmt != null);
 5771      Contract.Requires(theDecreases != null);
 5772
 3055773      if (theDecreases.Count == 0 && guard != null) {
 05774        loopStmt.InferredDecreases = true;
 05775        Expression prefix = null;
 05776        foreach (Expression guardConjunct in Expression.Conjuncts(guard)) {
 05777          Expression guess = null;
 05778          var neutralValue = Expression.CreateIntLiteral(guardConjunct.tok, -1);
 05779          if (guardConjunct is BinaryExpr bin) {
 05780            switch (bin.ResolvedOp) {
 5781              case BinaryExpr.ResolvedOpcode.Lt:
 5782              case BinaryExpr.ResolvedOpcode.Le:
 5783              case BinaryExpr.ResolvedOpcode.LtChar:
 5784              case BinaryExpr.ResolvedOpcode.LeChar:
 05785                if (bin.E0.Type.IsBigOrdinalType) {
 5786                  // we can't rely on subtracting ORDINALs, so let's just pick the upper bound and hope that works
 05787                  guess = bin.E1;
 05788                } else {
 5789                  // for A < B and A <= B, use the decreases B - A
 05790                  guess = Expression.CreateSubtract_TypeConvert(bin.E1, bin.E0);
 05791                }
 05792                break;
 5793              case BinaryExpr.ResolvedOpcode.Ge:
 5794              case BinaryExpr.ResolvedOpcode.Gt:
 5795              case BinaryExpr.ResolvedOpcode.GeChar:
 5796              case BinaryExpr.ResolvedOpcode.GtChar:
 05797                if (bin.E0.Type.IsBigOrdinalType) {
 5798                  // we can't rely on subtracting ORDINALs, so let's just pick the upper bound and hope that works
 05799                  guess = bin.E0;
 05800                } else {
 5801                  // for A >= B and A > B, use the decreases A - B
 05802                  guess = Expression.CreateSubtract_TypeConvert(bin.E0, bin.E1);
 05803                }
 05804                break;
 5805              case BinaryExpr.ResolvedOpcode.ProperSubset:
 5806              case BinaryExpr.ResolvedOpcode.Subset:
 05807                if (bin.E0.Type.AsSetType.Finite) {
 5808                  // for A < B and A <= B, use the decreases |B - A|
 05809                  guess = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E1, bin.E0), builtIns);
 05810                }
 05811                break;
 5812              case BinaryExpr.ResolvedOpcode.Superset:
 5813              case BinaryExpr.ResolvedOpcode.ProperSuperset:
 05814                if (bin.E0.Type.AsSetType.Finite) {
 5815                  // for A >= B and A > B, use the decreases |A - B|
 05816                  guess = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E0, bin.E1), builtIns);
 05817                }
 05818                break;
 5819              case BinaryExpr.ResolvedOpcode.ProperMultiSubset:
 5820              case BinaryExpr.ResolvedOpcode.MultiSubset:
 5821                // for A < B and A <= B, use the decreases |B - A|
 05822                guess = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E1, bin.E0), builtIns);
 05823                break;
 5824              case BinaryExpr.ResolvedOpcode.MultiSuperset:
 5825              case BinaryExpr.ResolvedOpcode.ProperMultiSuperset:
 5826                // for A >= B and A > B, use the decreases |A - B|
 05827                guess = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E0, bin.E1), builtIns);
 05828                break;
 5829              case BinaryExpr.ResolvedOpcode.Prefix:
 5830              case BinaryExpr.ResolvedOpcode.ProperPrefix:
 5831                // for "[] < B" and "[] <= B", use B
 05832                if (LiteralExpr.IsEmptySequence(bin.E0)) {
 05833                  guess = bin.E1;
 05834                }
 05835                break;
 5836              case BinaryExpr.ResolvedOpcode.NeqCommon:
 05837                if (bin.E0.Type.IsNumericBased() || bin.E0.Type.IsBitVectorType || bin.E0.Type.IsCharType) {
 5838                  // for A != B where A and B are numeric, use the absolute difference between A and B (that is: if A <=
 05839                  var AminusB = Expression.CreateSubtract_TypeConvert(bin.E0, bin.E1);
 05840                  var BminusA = Expression.CreateSubtract_TypeConvert(bin.E1, bin.E0);
 05841                  var test = Expression.CreateAtMost(bin.E0, bin.E1);
 05842                  guess = Expression.CreateITE(test, BminusA, AminusB);
 05843                } else if (bin.E0.Type.IsBigOrdinalType) {
 5844                  // if either of the operands is a literal, pick the other; otherwise, don't make any guess
 05845                  if (Expression.StripParens(bin.E0) is LiteralExpr) {
 05846                    guess = bin.E1;
 05847                  } else if (Expression.StripParens(bin.E1) is LiteralExpr) {
 05848                    guess = bin.E0;
 05849                  }
 05850                }
 05851                break;
 5852              case BinaryExpr.ResolvedOpcode.SetNeq:
 05853                if (bin.E0.Type.AsSetType.Finite) {
 5854                  // use |A - B| + |B - A|, but specialize it for the case where A or B is the empty set
 05855                  if (LiteralExpr.IsEmptySet(bin.E0)) {
 05856                    guess = bin.E1;
 05857                  } else if (LiteralExpr.IsEmptySet(bin.E1)) {
 05858                    guess = bin.E0;
 05859                  } else {
 05860                    var x = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E0, bin.E1), builtIns);
 05861                    var y = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E1, bin.E0), builtIns);
 05862                    guess = Expression.CreateAdd(x, y);
 05863                  }
 05864                }
 05865                break;
 5866              case BinaryExpr.ResolvedOpcode.MultiSetNeq:
 5867                // use |A - B| + |B - A|, but specialize it for the case where A or B is the empty multiset
 05868                if (LiteralExpr.IsEmptyMultiset(bin.E0)) {
 05869                  guess = bin.E1;
 05870                } else if (LiteralExpr.IsEmptyMultiset(bin.E1)) {
 05871                  guess = bin.E0;
 05872                } else {
 05873                  var x = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E0, bin.E1), builtIns);
 05874                  var y = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E1, bin.E0), builtIns);
 05875                  guess = Expression.CreateAdd(x, y);
 05876                }
 05877                break;
 5878              case BinaryExpr.ResolvedOpcode.SeqNeq:
 5879                // if either operand is [], then use the other
 05880                if (LiteralExpr.IsEmptySequence(bin.E0)) {
 05881                  guess = bin.E1;
 05882                } else if (LiteralExpr.IsEmptySequence(bin.E1)) {
 05883                  guess = bin.E0;
 05884                }
 05885                break;
 5886              default:
 05887                break;
 5888            }
 05889            if (bin.E0.Type.AsSetType != null) {
 05890              neutralValue = new SetDisplayExpr(bin.tok, bin.E0.Type.AsSetType.Finite, new List<Expression>()) {
 05891                Type = bin.E0.Type.NormalizeExpand()
 05892              };
 05893            } else if (bin.E0.Type.AsMultiSetType != null) {
 05894              neutralValue = new MultiSetDisplayExpr(bin.tok, new List<Expression>()) {
 05895                Type = bin.E0.Type.NormalizeExpand()
 05896              };
 05897            } else if (bin.E0.Type.AsSeqType != null) {
 05898              neutralValue = new SeqDisplayExpr(bin.tok, new List<Expression>()) {
 05899                Type = bin.E0.Type.NormalizeExpand()
 05900              };
 05901            } else if (bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 05902              neutralValue = Expression.CreateRealLiteral(bin.tok, BaseTypes.BigDec.FromInt(-1));
 05903            }
 05904          }
 05905          if (guess != null) {
 05906            if (prefix != null) {
 5907              // Make the following guess:  if prefix then guess else neutralValue
 05908              guess = Expression.CreateITE(prefix, guess, neutralValue);
 05909            }
 05910            theDecreases.Add(AutoGeneratedExpression.Create(guess));
 05911          }
 05912          if (prefix == null) {
 05913            prefix = guardConjunct;
 05914          } else {
 05915            prefix = Expression.CreateAnd(prefix, guardConjunct);
 05916          }
 05917        }
 05918      }
 3055919      if (enclosingMethod is IteratorDecl) {
 05920        var iter = (IteratorDecl)enclosingMethod;
 05921        var ie = new IdentifierExpr(loopStmt.Tok, iter.YieldCountVariable.Name);
 05922        ie.Var = iter.YieldCountVariable;  // resolve here
 05923        ie.Type = iter.YieldCountVariable.Type;  // resolve here
 05924        theDecreases.Insert(0, AutoGeneratedExpression.Create(ie));
 05925        loopStmt.InferredDecreases = true;
 05926      }
 3055927      if (loopStmt.InferredDecreases && theDecreases.Count != 0) {
 05928        string s = "decreases " + Util.Comma(theDecreases, expr => Printer.ExprToString(Options, expr));
 05929        reporter.Info(MessageSource.Resolver, loopStmt.Tok, s);
 05930      }
 3055931    }
 5932
 05933    public Expression VarDotMethod(IToken tok, string varname, string methodname) {
 05934      return new ApplySuffix(tok, null, new ExprDotName(tok, new IdentifierExpr(tok, varname), methodname, null), new Li
 05935    }
 5936
 05937    public Expression makeTemp(String prefix, AssignOrReturnStmt s, ResolutionContext resolutionContext, Expression ex) 
 05938      var temp = FreshTempVarName(prefix, resolutionContext.CodeContext);
 05939      var locvar = new LocalVariable(s.RangeToken, temp, ex.Type, false);
 05940      var id = new IdentifierExpr(s.Tok, temp);
 05941      var idlist = new List<Expression>() { id };
 05942      var lhss = new List<LocalVariable>() { locvar };
 05943      var rhss = new List<AssignmentRhs>() { new ExprRhs(ex) };
 05944      var up = new UpdateStmt(s.RangeToken, idlist, rhss);
 05945      s.ResolvedStatements.Add(new VarDeclStmt(s.RangeToken, lhss, up));
 05946      return id;
 05947    }
 5948
 05949    public void EnsureSupportsErrorHandling(IToken tok, Type tp, bool expectExtract, bool hasKeywordToken) {
 5950      // The "method not found" errors which will be generated here were already reported while
 5951      // resolving the statement, so we don't want them to reappear and redirect them into a sink.
 05952      var origReporter = this.reporter;
 05953      this.reporter = new ErrorReporterSink(Options, origReporter.OuterModule);
 5954
 05955      var isFailure = ResolveMember(tok, tp, "IsFailure", out _);
 05956      var propagateFailure = ResolveMember(tok, tp, "PropagateFailure", out _);
 05957      var extract = ResolveMember(tok, tp, "Extract", out _);
 5958
 05959      if (hasKeywordToken) {
 05960        if (isFailure == null || (extract != null) != expectExtract) {
 5961          // more details regarding which methods are missing have already been reported by regular resolution
 05962          origReporter.Error(MessageSource.Resolver, tok,
 05963            "The right-hand side of ':-', which is of type '{0}', with a keyword token must have function{1}", tp,
 05964            expectExtract
 05965              ? "s 'IsFailure()' and 'Extract()'"
 05966              : " 'IsFailure()', but not 'Extract()'");
 05967        }
 05968      } else {
 05969        if (isFailure == null || propagateFailure == null || (extract != null) != expectExtract) {
 5970          // more details regarding which methods are missing have already been reported by regular resolution
 05971          origReporter.Error(MessageSource.Resolver, tok,
 05972            "The right-hand side of ':-', which is of type '{0}', must have function{1}", tp,
 05973            expectExtract
 05974              ? "s 'IsFailure()', 'PropagateFailure()', and 'Extract()'"
 05975              : "s 'IsFailure()' and 'PropagateFailure()', but not 'Extract()'");
 05976        }
 05977      }
 5978
 05979      void checkIsFunction([CanBeNull] MemberDecl memberDecl, bool allowMethod) {
 05980        if (memberDecl == null || memberDecl is Function) {
 5981          // fine
 05982        } else if (allowMethod && memberDecl is Method) {
 5983          // give a deprecation warning, so we will remove this language feature around the Dafny 4 time frame
 05984          origReporter.Deprecated(MessageSource.Resolver, ErrorRegistry.NoneId, tok,
 05985            $"Support for member '{memberDecl.Name}' in type '{tp}' (used indirectly via a :- statement) being a method 
 05986            " declare it to be a function instead");
 05987        } else {
 5988          // not allowed
 05989          origReporter.Error(MessageSource.Resolver, tok,
 05990            $"Member '{memberDecl.Name}' in type '{tp}' (used indirectly via a :- statement) is expected to be a functio
 05991        }
 05992      }
 5993
 05994      checkIsFunction(isFailure, false);
 05995      if (!hasKeywordToken) {
 05996        checkIsFunction(propagateFailure, true);
 05997      }
 05998      if (expectExtract) {
 05999        checkIsFunction(extract, true);
 06000      }
 6001
 06002      this.reporter = origReporter;
 06003    }
 6004
 6005    /// <summary>
 6006    /// Check that "stmt" is a valid statment for the body of an assert-by, forall,
 6007    /// or calc-hint statement. In particular, check that the local variables assigned in
 6008    /// the bodies of these statements are declared in the statements, not in some enclosing
 6009    /// context.
 6010    /// </summary>
 06011    public void CheckLocalityUpdates(Statement stmt, ISet<LocalVariable> localsAllowedInUpdates, string where) {
 6012      Contract.Requires(stmt != null);
 6013      Contract.Requires(localsAllowedInUpdates != null);
 6014      Contract.Requires(where != null);
 6015
 06016      if (stmt is AssertStmt || stmt is ForallStmt || stmt is CalcStmt || stmt is ModifyStmt) {
 6017        // don't recurse, since CheckHintRestrictions will be called on that assert-by separately
 06018        return;
 06019      } else if (stmt is AssignSuchThatStmt) {
 06020        var s = (AssignSuchThatStmt)stmt;
 06021        foreach (var lhs in s.Lhss) {
 06022          CheckLocalityUpdatesLhs(lhs, localsAllowedInUpdates, @where);
 06023        }
 06024      } else if (stmt is AssignStmt) {
 06025        var s = (AssignStmt)stmt;
 06026        CheckLocalityUpdatesLhs(s.Lhs, localsAllowedInUpdates, @where);
 06027      } else if (stmt is CallStmt) {
 06028        var s = (CallStmt)stmt;
 06029        foreach (var lhs in s.Lhs) {
 06030          CheckLocalityUpdatesLhs(lhs, localsAllowedInUpdates, @where);
 06031        }
 06032      } else if (stmt is VarDeclStmt) {
 06033        var s = (VarDeclStmt)stmt;
 06034        s.Locals.Iter(local => localsAllowedInUpdates.Add(local));
 06035      } else if (stmt is ModifyStmt) {
 6036        // no further complaints (note, ghost interests have already checked for 'modify' statements)
 06037      } else if (stmt is BlockStmt) {
 06038        localsAllowedInUpdates = new HashSet<LocalVariable>(localsAllowedInUpdates);
 6039        // use this new set for the recursive calls
 06040      }
 6041
 06042      foreach (var ss in stmt.SubStatements) {
 06043        CheckLocalityUpdates(ss, localsAllowedInUpdates, where);
 06044      }
 06045    }
 6046
 06047    void CheckLocalityUpdatesLhs(Expression lhs, ISet<LocalVariable> localsAllowedInUpdates, string @where) {
 6048      Contract.Requires(lhs != null);
 6049      Contract.Requires(localsAllowedInUpdates != null);
 6050      Contract.Requires(where != null);
 6051
 06052      lhs = lhs.Resolved;
 06053      if (lhs is IdentifierExpr idExpr && !localsAllowedInUpdates.Contains(idExpr.Var)) {
 06054        reporter.Error(MessageSource.Resolver, lhs.tok, "{0} is not allowed to update a variable it doesn't declare", wh
 06055      }
 06056    }
 6057
 6058    class LazyString_OnTypeEquals {
 6059      Type t0;
 6060      Type t1;
 6061      string s;
 06062      public LazyString_OnTypeEquals(Type t0, Type t1, string s) {
 6063        Contract.Requires(t0 != null);
 6064        Contract.Requires(t1 != null);
 6065        Contract.Requires(s != null);
 06066        this.t0 = t0;
 06067        this.t1 = t1;
 06068        this.s = s;
 06069      }
 06070      public override string ToString() {
 06071        return t0.Equals(t1) ? s : "";
 06072      }
 6073    }
 6074
 2026075    void FindAllMembers(ClassDecl cl, string memberName, ISet<MemberDecl> foundSoFar) {
 6076      Contract.Requires(cl != null);
 6077      Contract.Requires(memberName != null);
 6078      Contract.Requires(foundSoFar != null);
 6079      MemberDecl member;
 4046080      if (classMembers[cl].TryGetValue(memberName, out member)) {
 2026081        foundSoFar.Add(member);
 2026082      }
 2026083      cl.ParentTraitHeads.ForEach(trait => FindAllMembers(trait, memberName, foundSoFar));
 2026084    }
 6085
 6086    // TODO move
 5526087    public static UserDefinedType GetThisType(IToken tok, TopLevelDeclWithMembers cl) {
 6088      Contract.Requires(tok != null);
 6089      Contract.Requires(cl != null);
 6090      Contract.Ensures(Contract.Result<UserDefinedType>() != null);
 6091
 11046092      if (cl is ClassDecl cls && cls.NonNullTypeDecl != null) {
 5526093        return UserDefinedType.FromTopLevelDecl(tok, cls.NonNullTypeDecl, cls.TypeArgs);
 06094      } else {
 06095        return UserDefinedType.FromTopLevelDecl(tok, cl, cl.TypeArgs);
 6096      }
 5526097    }
 6098
 6099    // TODO move
 06100    public static UserDefinedType GetReceiverType(IToken tok, MemberDecl member) {
 6101      Contract.Requires(tok != null);
 6102      Contract.Requires(member != null);
 6103      Contract.Ensures(Contract.Result<UserDefinedType>() != null);
 6104
 06105      return GetThisType(tok, (TopLevelDeclWithMembers)member.EnclosingClass);
 06106    }
 6107
 06108    Label/*?*/ ResolveDominatingLabelInExpr(IToken tok, string/*?*/ labelName, string expressionDescription, ResolutionC
 6109      Contract.Requires(tok != null);
 6110      Contract.Requires(expressionDescription != null);
 6111      Contract.Requires(resolutionContext != null);
 6112
 06113      Label label = null;
 06114      if (!resolutionContext.IsTwoState) {
 06115        reporter.Error(MessageSource.Resolver, tok, $"{expressionDescription} expressions are not allowed in this contex
 06116      } else if (labelName != null) {
 06117        label = DominatingStatementLabels.Find(labelName);
 06118        if (label == null) {
 06119          reporter.Error(MessageSource.Resolver, tok, $"no label '{labelName}' in scope at this time");
 06120        }
 06121      }
 06122      return label;
 06123    }
 6124
 06125    private Expression VarDotFunction(IToken tok, string varname, string functionname) {
 06126      return new ApplySuffix(tok, null, new ExprDotName(tok, new IdentifierExpr(tok, varname), functionname, null), new 
 06127    }
 6128
 6129    // TODO search for occurrences of "new LetExpr" which could benefit from this helper
 06130    private LetExpr LetPatIn(IToken tok, CasePattern<BoundVar> lhs, Expression rhs, Expression body) {
 06131      return new LetExpr(tok, new List<CasePattern<BoundVar>>() { lhs }, new List<Expression>() { rhs }, body, true);
 06132    }
 6133
 06134    private LetExpr LetVarIn(IToken tok, string name, Type tp, Expression rhs, Expression body) {
 06135      var lhs = new CasePattern<BoundVar>(tok, new BoundVar(tok, name, tp));
 06136      return LetPatIn(tok, lhs, rhs, body);
 06137    }
 6138
 6139    /// <summary>
 6140    ///  If expr.Lhs != null: Desugars "var x: T :- E; F" into "var temp := E; if temp.IsFailure() then temp.PropagateFa
 6141    ///  If expr.Lhs == null: Desugars "         :- E; F" into "var temp := E; if temp.IsFailure() then temp.PropagateFa
 6142    /// </summary>
 06143    public void ResolveLetOrFailExpr(LetOrFailExpr expr, ResolutionContext resolutionContext) {
 06144      var temp = FreshTempVarName("valueOrError", resolutionContext.CodeContext);
 06145      var tempType = new InferredTypeProxy();
 6146      // "var temp := E;"
 06147      expr.ResolvedExpression = LetVarIn(expr.tok, temp, tempType, expr.Rhs,
 06148        // "if temp.IsFailure()"
 06149        new ITEExpr(expr.tok, false, VarDotFunction(expr.tok, temp, "IsFailure"),
 06150          // "then temp.PropagateFailure()"
 06151          VarDotFunction(expr.tok, temp, "PropagateFailure"),
 06152          // "else"
 06153          expr.Lhs == null
 06154            // "F"
 06155            ? expr.Body
 06156            // "var x: T := temp.Extract(); F"
 06157            : LetPatIn(expr.tok, expr.Lhs, VarDotFunction(expr.tok, temp, "Extract"), expr.Body)));
 6158
 06159      ResolveExpression(expr.ResolvedExpression, resolutionContext);
 06160      expr.Type = expr.ResolvedExpression.Type;
 06161      bool expectExtract = (expr.Lhs != null);
 06162      EnsureSupportsErrorHandling(expr.tok, PartiallyResolveTypeForMemberSelection(expr.tok, tempType), expectExtract, f
 06163    }
 6164
 06165    public static Type SelectAppropriateArrowTypeForFunction(Function function, Dictionary<TypeParameter, Type> subst, B
 06166      return SelectAppropriateArrowType(function.tok,
 06167        function.Formals.ConvertAll(formal => formal.Type.Subst(subst)),
 06168        function.ResultType.Subst(subst),
 06169        function.Reads.Count != 0, function.Req.Count != 0,
 06170        builtIns);
 06171    }
 6172
 06173    public static Type SelectAppropriateArrowType(IToken tok, List<Type> typeArgs, Type resultType, bool hasReads, bool 
 6174      Contract.Requires(tok != null);
 6175      Contract.Requires(typeArgs != null);
 6176      Contract.Requires(resultType != null);
 06177      var arity = typeArgs.Count;
 06178      var typeArgsAndResult = Util.Snoc(typeArgs, resultType);
 06179      if (hasReads) {
 6180        // any arrow
 06181        return new ArrowType(tok, builtIns.ArrowTypeDecls[arity], typeArgsAndResult);
 06182      } else if (hasReq) {
 6183        // partial arrow
 06184        return new UserDefinedType(tok, ArrowType.PartialArrowTypeName(arity), builtIns.PartialArrowTypeDecls[arity], ty
 06185      } else {
 6186        // total arrow
 06187        return new UserDefinedType(tok, ArrowType.TotalArrowTypeName(arity), builtIns.TotalArrowTypeDecls[arity], typeAr
 6188      }
 06189    }
 6190
 6191    /// <summary>
 6192    /// Adds appropriate type constraints that says "expr" evaluates to an integer or (if "allowBitVector" is true) a
 6193    /// a bitvector.  The "errFormat" string can contain a "{0}", referring to the name of the type of "expr".
 6194    /// </summary>
 76606195    void ConstrainToIntegerType(Expression expr, bool allowBitVector, string errFormat) {
 6196      Contract.Requires(expr != null);
 6197      Contract.Requires(errFormat != null);
 76606198      var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, errFormat, expr.Type);
 76606199      ConstrainToIntegerType(expr.tok, expr.Type, allowBitVector, err);
 76606200    }
 6201
 6202    /// <summary>
 6203    /// Resolves a NestedMatchExpr by
 6204    /// 1 - checking that all of its patterns are linear
 6205    /// 2 - desugaring it into a decision tree of MatchExpr and ITEEXpr (for constant matching)
 6206    /// 3 - resolving the generated (sub)expression.
 6207    /// </summary>
 63936208    void ResolveNestedMatchExpr(NestedMatchExpr nestedMatchExpr, ResolutionContext resolutionContext) {
 6209      Contract.Requires(nestedMatchExpr != null);
 6210      Contract.Requires(resolutionContext != null);
 6211
 63936212      nestedMatchExpr.Resolve(this, resolutionContext);
 63936213    }
 6214
 6215    void ResolveCasePattern<VT>(CasePattern<VT> pat, Type sourceType, ResolutionContext resolutionContext)
 06216      where VT : class, IVariable {
 6217      Contract.Requires(pat != null);
 6218      Contract.Requires(sourceType != null);
 6219      Contract.Requires(resolutionContext != null);
 6220
 06221      DatatypeDecl dtd = null;
 06222      UserDefinedType udt = null;
 06223      if (sourceType.IsDatatype) {
 06224        udt = (UserDefinedType)sourceType.NormalizeExpand();
 06225        dtd = (DatatypeDecl)udt.ResolvedClass;
 06226      }
 6227      // Find the constructor in the given datatype
 6228      // If what was parsed was just an identifier, we will interpret it as a datatype constructor, if possible
 06229      DatatypeCtor ctor = null;
 06230      if (dtd != null) {
 06231        if (pat.Var == null || (pat.Var != null && pat.Var.Type is TypeProxy)) {
 06232          if (dtd.ConstructorsByName.TryGetValue(pat.Id, out ctor)) {
 06233            if (pat.Arguments == null) {
 06234              if (ctor.Formals.Count != 0) {
 6235                // Leave this as a variable
 06236              } else {
 6237                // Convert to a constructor
 06238                pat.MakeAConstructor();
 06239                pat.Ctor = ctor;
 06240                pat.Var = default(VT);
 06241              }
 06242            } else {
 06243              pat.Ctor = ctor;
 06244              pat.Var = default(VT);
 06245            }
 06246          }
 06247        }
 06248      }
 6249
 06250      if (pat.Var != null) {
 6251        // this is a simple resolution
 06252        var v = pat.Var;
 06253        if (resolutionContext.IsGhost) {
 06254          v.MakeGhost();
 06255        }
 06256        ResolveType(v.Tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 6257        // Note, the following type constraint checks that the RHS type can be assigned to the new variable on the left.
 6258        // does not check that the entire RHS can be assigned to something of the type of the pattern on the left.  For 
 6259        // a type declared as "datatype Atom<T> = MakeAtom(T)", where T is a non-variant type argument.  Suppose the RHS
 6260        // and that the LHS is the pattern MakeAtom(x: int).  This is okay, despite the fact that Atom<nat> is not assig
 6261        // The reason is that the purpose of the pattern on the left is really just to provide a skeleton to introduce b
 06262        EagerAddAssignableConstraint(v.Tok, v.Type, sourceType, "type of corresponding source/RHS ({1}) does not match t
 06263        pat.AssembleExpr(null);
 06264        return;
 6265      }
 06266      if (dtd == null) {
 6267        // look up the name of the pattern's constructor
 6268        Tuple<DatatypeCtor, bool> pair;
 06269        if (moduleInfo.Ctors.TryGetValue(pat.Id, out pair) && !pair.Item2) {
 06270          ctor = pair.Item1;
 06271          pat.Ctor = ctor;
 06272          dtd = ctor.EnclosingDatatype;
 06273          var typeArgs = new List<Type>();
 06274          foreach (var xt in dtd.TypeArgs) {
 06275            typeArgs.Add(new InferredTypeProxy());
 06276          }
 06277          udt = new UserDefinedType(pat.tok, dtd.Name, dtd, typeArgs);
 06278          ConstrainSubtypeRelation(udt, sourceType, pat.tok, "type of RHS ({0}) does not match type of bound variable '{
 06279        }
 06280      }
 06281      if (dtd == null && ctor == null) {
 06282        reporter.Error(MessageSource.Resolver, pat.tok, "to use a pattern, the type of the source/RHS expression must be
 06283      } else if (ctor == null) {
 06284        reporter.Error(MessageSource.Resolver, pat.tok, "constructor {0} does not exist in datatype {1}", pat.Id, dtd.Na
 06285      } else {
 06286        if (pat.Arguments == null) {
 06287          if (ctor.Formals.Count == 0) {
 6288            // The Id matches a constructor of the correct type and 0 arguments,
 6289            // so make it a nullary constructor, not a variable
 06290            pat.MakeAConstructor();
 06291          }
 06292        } else {
 06293          if (ctor.Formals.Count != pat.Arguments.Count) {
 06294            reporter.Error(MessageSource.Resolver, pat.tok, "pattern for constructor {0} has wrong number of formals (fo
 06295          }
 06296        }
 6297        // build the type-parameter substitution map for this use of the datatype
 06298        Contract.Assert(dtd.TypeArgs.Count == udt.TypeArgs.Count);  // follows from the type previously having been succ
 06299        var subst = TypeParameter.SubstitutionMap(dtd.TypeArgs, udt.TypeArgs);
 6300        // recursively call ResolveCasePattern on each of the arguments
 06301        var j = 0;
 06302        if (pat.Arguments != null) {
 06303          foreach (var arg in pat.Arguments) {
 06304            if (j < ctor.Formals.Count) {
 06305              var formal = ctor.Formals[j];
 06306              Type st = formal.Type.Subst(subst);
 06307              ResolveCasePattern(arg, st, resolutionContext.WithGhost(resolutionContext.IsGhost || formal.IsGhost));
 06308            }
 06309            j++;
 06310          }
 06311        }
 06312        if (j == ctor.Formals.Count) {
 06313          pat.AssembleExpr(udt.TypeArgs);
 06314        }
 06315      }
 06316    }
 6317
 3066318    private List<DefaultValueExpression> allDefaultValueExpressions = new List<DefaultValueExpression>();
 6319
 6320    /// <summary>
 6321    /// This method is called at the tail end of Pass1 of the Resolver.
 6322    /// </summary>
 8886323    void FillInDefaultValueExpressions() {
 8886324      var visited = new Dictionary<DefaultValueExpression, WorkProgress>();
 26646325      foreach (var e in allDefaultValueExpressions) {
 06326        FillInDefaultValueExpression(e, visited);
 06327      }
 8886328      allDefaultValueExpressions.Clear();
 8886329    }
 6330
 6331    enum WorkProgress { BeingVisited, Done }
 6332
 06333    void FillInDefaultValueExpression(DefaultValueExpression expr, Dictionary<DefaultValueExpression, WorkProgress> visi
 6334      Contract.Requires(expr != null);
 6335      Contract.Requires(visited != null);
 6336      Contract.Ensures(expr.ResolvedExpression != null);
 6337
 06338      if (visited.TryGetValue(expr, out var p)) {
 06339        if (p == WorkProgress.Done) {
 06340          Contract.Assert(expr.ResolvedExpression != null);
 06341        } else {
 6342          // there is a cycle
 06343          reporter.Error(MessageSource.Resolver, expr, "default-valued expressions are cyclicly dependent; this is not a
 6344          // nevertheless, to avoid any issues in the resolver, fill in the .ResolvedExpression field with something
 06345          expr.ResolvedExpression = Expression.CreateBoolLiteral(expr.tok, false);
 06346        }
 06347        return;
 6348      }
 06349      Contract.Assert(expr.ResolvedExpression == null);
 6350
 06351      visited.Add(expr, WorkProgress.BeingVisited);
 06352      var s = new DefaultValueSubstituter(this, visited, expr.Receiver, expr.SubstMap, expr.TypeMap);
 06353      expr.ResolvedExpression = s.Substitute(expr.Formal.DefaultValue);
 06354      visited[expr] = WorkProgress.Done;
 06355    }
 6356
 6357    class DefaultValueSubstituter : Substituter {
 6358      private readonly Resolver resolver;
 6359      private readonly Dictionary<DefaultValueExpression, WorkProgress> visited;
 6360      public DefaultValueSubstituter(Resolver resolver, Dictionary<DefaultValueExpression, WorkProgress> visited,
 6361        Expression /*?*/ receiverReplacement, Dictionary<IVariable, Expression> substMap, Dictionary<TypeParameter, Type
 06362        : base(receiverReplacement, substMap, typeMap) {
 6363        Contract.Requires(resolver != null);
 6364        Contract.Requires(visited != null);
 06365        this.resolver = resolver;
 06366        this.visited = visited;
 06367      }
 6368
 06369      public override Expression Substitute(Expression expr) {
 06370        if (expr is DefaultValueExpression dve) {
 06371          resolver.FillInDefaultValueExpression(dve, visited);
 06372          Contract.Assert(dve.ResolvedExpression != null); // postcondition of FillInDefaultValueExpression
 06373        }
 06374        return base.Substitute(expr);
 06375      }
 6376    }
 6377
 6378    public Dictionary<TypeParameter, Type> BuildTypeArgumentSubstitute(Dictionary<TypeParameter, Type> typeArgumentSubst
 234606379      Type/*?*/ receiverTypeBound = null) {
 6380      Contract.Requires(typeArgumentSubstitutions != null);
 6381
 234606382      var subst = new Dictionary<TypeParameter, Type>();
 1779336383      foreach (var entry in typeArgumentSubstitutions) {
 358516384        subst.Add(entry.Key, entry.Value);
 358516385      }
 6386
 234606387      if (SelfTypeSubstitution != null) {
 06388        foreach (var entry in SelfTypeSubstitution) {
 06389          subst.Add(entry.Key, entry.Value);
 06390        }
 06391      }
 6392
 469206393      if (receiverTypeBound != null) {
 234606394        subst = AddParentTypeParameterSubstitutions(subst, receiverTypeBound);
 234606395      }
 6396
 234606397      return subst;
 234606398    }
 6399
 234606400    public static Dictionary<TypeParameter, Type> AddParentTypeParameterSubstitutions(Dictionary<TypeParameter, Type> su
 6401      TopLevelDeclWithMembers cl;
 234606402      var udt = receiverType?.AsNonNullRefType;
 234606403      if (udt != null) {
 06404        cl = (TopLevelDeclWithMembers)((NonNullTypeDecl)udt.ResolvedClass).ViewAsClass;
 234606405      } else {
 234606406        udt = receiverType.NormalizeExpand() as UserDefinedType;
 234606407        cl = udt?.ResolvedClass as TopLevelDeclWithMembers;
 234606408      }
 463606409      if (cl != null) {
 687006410        foreach (var entry in cl.ParentFormalTypeParametersToActuals) {
 06411          var v = entry.Value.Subst(subst);
 06412          subst.Add(entry.Key, v);
 06413        }
 229006414      }
 6415
 234606416      return subst;
 234606417    }
 6418
 82046419    public static string GhostPrefix(bool isGhost) {
 82046420      return isGhost ? "ghost " : "";
 82046421    }
 6422
 06423    private static ModuleSignature GetSignatureExt(ModuleSignature sig, bool useCompileSignatures) {
 6424      Contract.Requires(sig != null);
 6425      Contract.Ensures(Contract.Result<ModuleSignature>() != null);
 06426      if (useCompileSignatures) {
 06427        while (sig.CompileSignature != null) {
 06428          sig = sig.CompileSignature;
 06429        }
 06430      }
 06431      return sig;
 06432    }
 6433
 06434    private ModuleSignature GetSignature(ModuleSignature sig) {
 06435      return GetSignatureExt(sig, useCompileSignatures);
 06436    }
 6437
 2766438    public static Expression GetImpliedTypeConstraint(IVariable bv, Type ty) {
 2766439      return GetImpliedTypeConstraint(Expression.CreateIdentExpr(bv), ty);
 2766440    }
 6441
 5526442    public static Expression GetImpliedTypeConstraint(Expression e, Type ty) {
 6443      Contract.Requires(e != null);
 6444      Contract.Requires(ty != null);
 5526445      ty = ty.NormalizeExpandKeepConstraints();
 5526446      var udt = ty as UserDefinedType;
 8286447      if (udt != null) {
 2766448        if (udt.ResolvedClass is NewtypeDecl) {
 06449          var dd = (NewtypeDecl)udt.ResolvedClass;
 06450          var c = GetImpliedTypeConstraint(e, dd.BaseType);
 06451          if (dd.Var != null) {
 06452            Dictionary<IVariable, Expression/*!*/> substMap = new Dictionary<IVariable, Expression>();
 06453            substMap.Add(dd.Var, e);
 06454            Substituter sub = new Substituter(null, substMap, new Dictionary<TypeParameter, Type>());
 06455            c = Expression.CreateAnd(c, sub.Substitute(dd.Constraint));
 06456          }
 06457          return c;
 5526458        } else if (udt.ResolvedClass is SubsetTypeDecl) {
 2766459          var dd = (SubsetTypeDecl)udt.ResolvedClass;
 2766460          var c = GetImpliedTypeConstraint(e, dd.RhsWithArgument(udt.TypeArgs));
 2766461          Dictionary<IVariable, Expression/*!*/> substMap = new Dictionary<IVariable, Expression>();
 2766462          substMap.Add(dd.Var, e);
 2766463          Substituter sub = new Substituter(null, substMap, new Dictionary<TypeParameter, Type>());
 2766464          c = Expression.CreateAnd(c, sub.Substitute(dd.Constraint));
 2766465          return c;
 6466        }
 06467      }
 2766468      return Expression.CreateBoolLiteral(e.tok, true);
 5526469    }
 6470
 6471    /// <summary>
 6472    /// Returns the set of free variables in "expr".
 6473    /// Requires "expr" to be successfully resolved.
 6474    /// Ensures that the set returned has no aliases.
 6475    /// </summary>
 06476    static ISet<IVariable> FreeVariables(Expression expr) {
 6477      Contract.Requires(expr != null);
 6478      Contract.Ensures(expr.Type != null);
 6479
 06480      if (expr is IdentifierExpr) {
 06481        var e = (IdentifierExpr)expr;
 06482        return new HashSet<IVariable>() { e.Var };
 6483
 06484      } else if (expr is QuantifierExpr) {
 06485        var e = (QuantifierExpr)expr;
 06486        Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 6487
 06488        var s = FreeVariables(e.LogicalBody());
 06489        foreach (var bv in e.BoundVars) {
 06490          s.Remove(bv);
 06491        }
 06492        return s;
 06493      } else if (expr is NestedMatchExpr) {
 06494        var e = (NestedMatchExpr)expr;
 06495        var s = FreeVariables(e.Source);
 06496        foreach (NestedMatchCaseExpr mc in e.Cases) {
 06497          var t = FreeVariables(mc.Body);
 06498          foreach (var bv in mc.Pat.Children.OfType<IdPattern>()) {
 06499            if (bv.BoundVar != null) {
 06500              t.Remove(bv.BoundVar);
 06501            }
 06502          }
 06503          s.UnionWith(t);
 06504        }
 06505        return s;
 06506      } else if (expr is MatchExpr) {
 06507        var e = (MatchExpr)expr;
 06508        var s = FreeVariables(e.Source);
 06509        foreach (MatchCaseExpr mc in e.Cases) {
 06510          var t = FreeVariables(mc.Body);
 06511          foreach (var bv in mc.Arguments) {
 06512            t.Remove(bv);
 06513          }
 06514          s.UnionWith(t);
 06515        }
 06516        return s;
 6517
 06518      } else if (expr is LambdaExpr) {
 06519        var e = (LambdaExpr)expr;
 06520        var s = FreeVariables(e.Term);
 06521        if (e.Range != null) {
 06522          s.UnionWith(FreeVariables(e.Range));
 06523        }
 06524        foreach (var fe in e.Reads) {
 06525          s.UnionWith(FreeVariables(fe.E));
 06526        }
 06527        foreach (var bv in e.BoundVars) {
 06528          s.Remove(bv);
 06529        }
 06530        return s;
 6531
 06532      } else {
 06533        ISet<IVariable> s = null;
 06534        foreach (var e in expr.SubExpressions) {
 06535          var t = FreeVariables(e);
 06536          if (s == null) {
 06537            s = t;
 06538          } else {
 06539            s.UnionWith(t);
 06540          }
 06541        }
 06542        return s == null ? new HashSet<IVariable>() : s;
 6543      }
 06544    }
 6545
 6546    /// <summary>
 6547    /// An error message for the type constraint for between a sequence select expression's actual and expected types.
 6548    /// If resolution successfully determines the sequences' element types, then this derived class mentions those
 6549    /// element types as clarifying context to the user.
 6550    /// </summary>
 6551    private class SeqSelectOneErrorMsg : TypeConstraint.ErrorMsgWithToken {
 1916552      private static readonly string BASE_MESSAGE_FORMAT = "sequence has type {0} which is incompatible with expected ty
 1916553      private static readonly string ELEMENT_DETAIL_MESSAGE_FORMAT = " (element type {0} is incompatible with {1})";
 6554
 6555      private readonly Type exprSeqType;
 6556      private readonly Type expectedSeqType;
 6557
 6558      public override string Msg {
 06559        get {
 6560          // Resolution might resolve exprSeqType/expectedSeqType to not be sequences at all.
 6561          // In that case, it isn't possible to get the corresponding element types.
 06562          var rawExprElementType = exprSeqType.AsSeqType?.Arg;
 06563          var rawExpectedElementType = expectedSeqType.AsSeqType?.Arg;
 06564          if (rawExprElementType == null || rawExpectedElementType == null) {
 06565            return base.Msg;
 6566          }
 6567
 06568          var elementTypes = RemoveAmbiguity(new object[] { rawExprElementType, rawExpectedElementType });
 06569          Contract.Assert(elementTypes.Length == 2);
 06570          var exprElementType = elementTypes[0].ToString();
 06571          var expectedElementType = elementTypes[1].ToString();
 6572
 06573          string detail = string.Format(ELEMENT_DETAIL_MESSAGE_FORMAT, exprElementType, expectedElementType);
 06574          return base.Msg + detail;
 06575        }
 6576      }
 6577
 6578      public SeqSelectOneErrorMsg(IToken tok, Type exprSeqType, Type expectedSeqType)
 605066579        : base(tok, BASE_MESSAGE_FORMAT, exprSeqType, expectedSeqType) {
 6580        Contract.Requires(exprSeqType != null);
 6581        Contract.Requires(expectedSeqType != null);
 302536582        this.exprSeqType = exprSeqType;
 302536583        this.expectedSeqType = expectedSeqType;
 302536584      }
 6585    }
 6586
 6587    /// <summary>
 6588    /// Note: this method is allowed to be called even if "type" does not make sense for "op", as might be the case if
 6589    /// resolution of the binary expression failed.  If so, an arbitrary resolved opcode is returned.
 6590    /// Usually, the type of the right-hand operand is used to determine the resolved operator (hence, the shorter
 6591    /// name "operandType" instead of, say, "rightOperandType").
 6592    /// </summary>
 1499646593    public static BinaryExpr.ResolvedOpcode ResolveOp(BinaryExpr.Opcode op, Type leftOperandType, Type operandType) {
 6594      Contract.Requires(leftOperandType != null);
 6595      Contract.Requires(operandType != null);
 1499646596      leftOperandType = leftOperandType.NormalizeExpand();
 1499646597      operandType = operandType.NormalizeExpand();
 1499646598      switch (op) {
 1606599        case BinaryExpr.Opcode.Iff: return BinaryExpr.ResolvedOpcode.Iff;
 117776600        case BinaryExpr.Opcode.Imp: return BinaryExpr.ResolvedOpcode.Imp;
 1646601        case BinaryExpr.Opcode.Exp: return BinaryExpr.ResolvedOpcode.Imp;
 261996602        case BinaryExpr.Opcode.And: return BinaryExpr.ResolvedOpcode.And;
 42676603        case BinaryExpr.Opcode.Or: return BinaryExpr.ResolvedOpcode.Or;
 6604        case BinaryExpr.Opcode.Eq:
 493316605          if (operandType is SetType) {
 1986606            return BinaryExpr.ResolvedOpcode.SetEq;
 504736607          } else if (operandType is MultiSetType) {
 15386608            return BinaryExpr.ResolvedOpcode.MultiSetEq;
 499476609          } else if (operandType is SeqType) {
 25506610            return BinaryExpr.ResolvedOpcode.SeqEq;
 477936611          } else if (operandType is MapType) {
 29466612            return BinaryExpr.ResolvedOpcode.MapEq;
 419016613          } else {
 419016614            return BinaryExpr.ResolvedOpcode.EqCommon;
 6615          }
 6616        case BinaryExpr.Opcode.Neq:
 31156617          if (operandType is SetType) {
 06618            return BinaryExpr.ResolvedOpcode.SetNeq;
 31456619          } else if (operandType is MultiSetType) {
 306620            return BinaryExpr.ResolvedOpcode.MultiSetNeq;
 31156621          } else if (operandType is SeqType) {
 306622            return BinaryExpr.ResolvedOpcode.SeqNeq;
 30556623          } else if (operandType is MapType) {
 06624            return BinaryExpr.ResolvedOpcode.MapNeq;
 30556625          } else {
 30556626            return BinaryExpr.ResolvedOpcode.NeqCommon;
 6627          }
 6628        case BinaryExpr.Opcode.Disjoint:
 2796629          if (operandType is MultiSetType) {
 976630            return BinaryExpr.ResolvedOpcode.MultiSetDisjoint;
 856631          } else {
 856632            return BinaryExpr.ResolvedOpcode.Disjoint;
 6633          }
 6634        case BinaryExpr.Opcode.Lt:
 95516635          if (operandType.IsIndDatatype) {
 06636            return BinaryExpr.ResolvedOpcode.RankLt;
 95816637          } else if (operandType is SetType) {
 306638            return BinaryExpr.ResolvedOpcode.ProperSubset;
 95416639          } else if (operandType is MultiSetType) {
 206640            return BinaryExpr.ResolvedOpcode.ProperMultiSubset;
 95066641          } else if (operandType is SeqType) {
 56642            return BinaryExpr.ResolvedOpcode.ProperPrefix;
 95236643          } else if (operandType is CharType) {
 276644            return BinaryExpr.ResolvedOpcode.LtChar;
 94696645          } else {
 94696646            return BinaryExpr.ResolvedOpcode.Lt;
 6647          }
 6648        case BinaryExpr.Opcode.Le:
 79346649          if (operandType is SetType) {
 206650            return BinaryExpr.ResolvedOpcode.Subset;
 79446651          } else if (operandType is MultiSetType) {
 506652            return BinaryExpr.ResolvedOpcode.MultiSubset;
 78546653          } else if (operandType is SeqType) {
 106654            return BinaryExpr.ResolvedOpcode.Prefix;
 78596655          } else if (operandType is CharType) {
 256656            return BinaryExpr.ResolvedOpcode.LeChar;
 78096657          } else {
 78096658            return BinaryExpr.ResolvedOpcode.Le;
 6659          }
 6660        case BinaryExpr.Opcode.LeftShift:
 06661          return BinaryExpr.ResolvedOpcode.LeftShift;
 6662        case BinaryExpr.Opcode.RightShift:
 06663          return BinaryExpr.ResolvedOpcode.RightShift;
 6664        case BinaryExpr.Opcode.Add:
 30966665          if (operandType is SetType) {
 656666            return BinaryExpr.ResolvedOpcode.Union;
 31486667          } else if (operandType is MultiSetType) {
 1826668            return BinaryExpr.ResolvedOpcode.MultiSetUnion;
 32626669          } else if (operandType is MapType) {
 4786670            return BinaryExpr.ResolvedOpcode.MapMerge;
 32746671          } else if (operandType is SeqType) {
 9686672            return BinaryExpr.ResolvedOpcode.Concat;
 13386673          } else {
 13386674            return BinaryExpr.ResolvedOpcode.Add;
 6675          }
 6676        case BinaryExpr.Opcode.Sub:
 30576677          if (leftOperandType is MapType) {
 4716678            return BinaryExpr.ResolvedOpcode.MapSubtraction;
 21456679          } else if (operandType is SetType) {
 306680            return BinaryExpr.ResolvedOpcode.SetDifference;
 22626681          } else if (operandType is MultiSetType) {
 1776682            return BinaryExpr.ResolvedOpcode.MultiSetDifference;
 19086683          } else {
 19086684            return BinaryExpr.ResolvedOpcode.Sub;
 6685          }
 6686        case BinaryExpr.Opcode.Mul:
 7536687          if (operandType is SetType) {
 706688            return BinaryExpr.ResolvedOpcode.Intersection;
 8036689          } else if (operandType is MultiSetType) {
 1906690            return BinaryExpr.ResolvedOpcode.MultiSetIntersection;
 4236691          } else {
 4236692            return BinaryExpr.ResolvedOpcode.Mul;
 6693          }
 6694        case BinaryExpr.Opcode.Gt:
 154336695          if (operandType.IsDatatype) {
 06696            return BinaryExpr.ResolvedOpcode.RankGt;
 154536697          } else if (operandType is SetType) {
 206698            return BinaryExpr.ResolvedOpcode.ProperSuperset;
 154586699          } else if (operandType is MultiSetType) {
 456700            return BinaryExpr.ResolvedOpcode.ProperMultiSuperset;
 154036701          } else if (operandType is CharType) {
 356702            return BinaryExpr.ResolvedOpcode.GtChar;
 153336703          } else {
 153336704            return BinaryExpr.ResolvedOpcode.Gt;
 6705          }
 6706        case BinaryExpr.Opcode.Ge:
 43896707          if (operandType is SetType) {
 206708            return BinaryExpr.ResolvedOpcode.Superset;
 43696709          } else if (operandType is MultiSetType) {
 206710            return BinaryExpr.ResolvedOpcode.MultiSuperset;
 43896711          } else if (operandType is CharType) {
 606712            return BinaryExpr.ResolvedOpcode.GeChar;
 42696713          } else {
 42696714            return BinaryExpr.ResolvedOpcode.Ge;
 6715          }
 6716        case BinaryExpr.Opcode.In:
 80806717          if (operandType is SetType) {
 156718            return BinaryExpr.ResolvedOpcode.InSet;
 80906719          } else if (operandType is MultiSetType) {
 406720            return BinaryExpr.ResolvedOpcode.InMultiSet;
 159506721          } else if (operandType is MapType) {
 79406722            return BinaryExpr.ResolvedOpcode.InMap;
 706723          } else {
 706724            return BinaryExpr.ResolvedOpcode.InSeq;
 6725          }
 6726        case BinaryExpr.Opcode.NotIn:
 3286727          if (operandType is SetType) {
 806728            return BinaryExpr.ResolvedOpcode.NotInSet;
 1886729          } else if (operandType is MultiSetType) {
 206730            return BinaryExpr.ResolvedOpcode.NotInMultiSet;
 2546731          } else if (operandType is MapType) {
 1066732            return BinaryExpr.ResolvedOpcode.NotInMap;
 426733          } else {
 426734            return BinaryExpr.ResolvedOpcode.NotInSeq;
 6735          }
 16076736        case BinaryExpr.Opcode.Div: return BinaryExpr.ResolvedOpcode.Div;
 14806737        case BinaryExpr.Opcode.Mod: return BinaryExpr.ResolvedOpcode.Mod;
 06738        case BinaryExpr.Opcode.BitwiseAnd: return BinaryExpr.ResolvedOpcode.BitwiseAnd;
 06739        case BinaryExpr.Opcode.BitwiseOr: return BinaryExpr.ResolvedOpcode.BitwiseOr;
 06740        case BinaryExpr.Opcode.BitwiseXor: return BinaryExpr.ResolvedOpcode.BitwiseXor;
 6741        default:
 06742          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected operator
 6743      }
 1499646744    }
 6745
 6746    /// <summary>
 6747    /// This method adds to "friendlyCalls" all
 6748    ///     inductive calls                                     if !co
 6749    ///     greatest predicate calls and codatatype equalities  if co
 6750    /// that occur in positive positions and not under
 6751    ///     universal quantification                            if !co
 6752    ///     existential quantification.                         if co
 6753    /// If "expr" is the
 6754    ///     precondition of a least lemma                       if !co
 6755    ///     postcondition of a greatest lemma,                  if co
 6756    /// then the "friendlyCalls" are the subexpressions that need to be replaced in order
 6757    /// to create the
 6758    ///     precondition                                        if !co
 6759    ///     postcondition                                       if co
 6760    /// of the corresponding prefix lemma.
 6761    /// </summary>
 06762    void CollectFriendlyCallsInExtremeLemmaSpecification(Expression expr, bool position, ISet<Expression> friendlyCalls,
 6763      Contract.Requires(expr != null);
 6764      Contract.Requires(friendlyCalls != null);
 06765      var visitor = new CollectFriendlyCallsInSpec_Visitor(this, friendlyCalls, co, context);
 06766      visitor.Visit(expr, position ? CallingPosition.Positive : CallingPosition.Negative);
 06767    }
 6768
 6769    class CollectFriendlyCallsInSpec_Visitor : FindFriendlyCalls_Visitor {
 6770      readonly ISet<Expression> friendlyCalls;
 6771      readonly ExtremeLemma Context;
 6772      public CollectFriendlyCallsInSpec_Visitor(Resolver resolver, ISet<Expression> friendlyCalls, bool co, ExtremeLemma
 06773        : base(resolver, co, context.KNat) {
 6774        Contract.Requires(resolver != null);
 6775        Contract.Requires(friendlyCalls != null);
 6776        Contract.Requires(context != null);
 06777        this.friendlyCalls = friendlyCalls;
 06778        this.Context = context;
 06779      }
 06780      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 06781        if (cp == CallingPosition.Neither) {
 6782          // no friendly calls in "expr"
 06783          return false;  // don't recurse into subexpressions
 6784        }
 06785        if (expr is FunctionCallExpr) {
 06786          if (cp == CallingPosition.Positive) {
 06787            var fexp = (FunctionCallExpr)expr;
 06788            if (IsCoContext ? fexp.Function is GreatestPredicate : fexp.Function is LeastPredicate) {
 06789              if (Context.KNat != ((ExtremePredicate)fexp.Function).KNat) {
 06790                resolver.KNatMismatchError(expr.tok, Context.Name, Context.TypeOfK, ((ExtremePredicate)fexp.Function).Ty
 06791              } else {
 06792                friendlyCalls.Add(fexp);
 06793              }
 06794            }
 06795          }
 06796          return false;  // don't explore subexpressions any further
 06797        } else if (expr is BinaryExpr && IsCoContext) {
 06798          var bin = (BinaryExpr)expr;
 06799          if (cp == CallingPosition.Positive && bin.ResolvedOp == BinaryExpr.ResolvedOpcode.EqCommon && bin.E0.Type.IsCo
 06800            friendlyCalls.Add(bin);
 06801            return false;  // don't explore subexpressions any further
 06802          } else if (cp == CallingPosition.Negative && bin.ResolvedOp == BinaryExpr.ResolvedOpcode.NeqCommon && bin.E0.T
 06803            friendlyCalls.Add(bin);
 06804            return false;  // don't explore subexpressions any further
 6805          }
 06806        }
 06807        return base.VisitOneExpr(expr, ref cp);
 06808      }
 6809    }
 6810  }
 6811
 6812  abstract class ResolverTopDownVisitor<T> : TopDownVisitor<T> {
 6813    protected Resolver resolver;
 6814    public ResolverTopDownVisitor(Resolver resolver) {
 6815      Contract.Requires(resolver != null);
 6816      this.resolver = resolver;
 6817    }
 6818  }
 6819
 6820  class CoCallResolution {
 6821    readonly Function currentFunction;
 6822    readonly bool dealsWithCodatatypes;
 6823    public bool HasIntraClusterCallsInDestructiveContexts = false;
 6824    public readonly List<CoCallInfo> FinalCandidates = new List<CoCallInfo>();
 6825
 6826    public CoCallResolution(Function currentFunction, bool dealsWithCodatatypes) {
 6827      Contract.Requires(currentFunction != null);
 6828      this.currentFunction = currentFunction;
 6829      this.dealsWithCodatatypes = dealsWithCodatatypes;
 6830    }
 6831
 6832    /// <summary>
 6833    /// Determines which calls in "expr" can be considered to be co-calls, which co-constructor
 6834    /// invocations host such co-calls, and which destructor operations are not allowed.
 6835    /// Also records whether or not there are any intra-cluster calls in a destructive context.
 6836    /// Assumes "expr" to have been successfully resolved.
 6837    /// </summary>
 6838    public void CheckCoCalls(Expression expr) {
 6839      Contract.Requires(expr != null);
 6840      CheckCoCalls(expr, 0, null, FinalCandidates);
 6841    }
 6842
 6843    public struct CoCallInfo {
 6844      public readonly FunctionCallExpr CandidateCall;
 6845      public readonly DatatypeValue EnclosingCoConstructor;
 6846      public CoCallInfo(FunctionCallExpr candidateCall, DatatypeValue enclosingCoConstructor) {
 6847        Contract.Requires(candidateCall != null);
 6848        Contract.Requires(enclosingCoConstructor != null);
 6849        CandidateCall = candidateCall;
 6850        EnclosingCoConstructor = enclosingCoConstructor;
 6851      }
 6852    }
 6853
 6854    /// <summary>
 6855    /// Recursively goes through the entire "expr".  Every call within the same recursive cluster is a potential
 6856    /// co-call.  If the call is determined not to be a co-recursive call, then its .CoCall field is filled in;
 6857    /// if the situation deals with co-datatypes, then one of the NoBecause... values is chosen (rather
 6858    /// than just No), so that any error message that may later be produced when trying to prove termination of the
 6859    /// recursive call can include a note pointing out that the call was not selected to be a co-call.
 6860    /// If the call looks like it is guarded, then it is added to the list "coCandicates", so that a later analysis
 6861    /// can either set all of those .CoCall fields to Yes or to NoBecauseRecursiveCallsInDestructiveContext, depending
 6862    /// on other intra-cluster calls.
 6863    /// The "destructionLevel" indicates how many pending co-destructors the context has.  It may be infinity (int.MaxVa
 6864    /// if the enclosing context has no easy way of controlling the uses of "expr" (for example, if the enclosing contex
 6865    /// passes "expr" to a function or binds "expr" to a variable).  It is never negative -- excess co-constructors are
 6866    /// not considered an asset, and any immediately enclosing co-constructor is passed in as a non-null "coContext" any
 6867    /// "coContext" is non-null if the immediate context is a co-constructor.
 6868    /// </summary>
 6869    void CheckCoCalls(Expression expr, int destructionLevel, DatatypeValue coContext, List<CoCallInfo> coCandidates, Fun
 6870      Contract.Requires(expr != null);
 6871
 6872      Contract.Requires(0 <= destructionLevel);
 6873      Contract.Requires(coCandidates != null);
 6874      expr = expr.Resolved;
 6875      if (expr is DatatypeValue) {
 6876        var e = (DatatypeValue)expr;
 6877        if (e.Ctor.EnclosingDatatype is CoDatatypeDecl) {
 6878          int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel == 0 ? 0 : destructionLevel - 1;
 6879          foreach (var arg in e.Arguments) {
 6880            CheckCoCalls(arg, dl, e, coCandidates);
 6881          }
 6882          return;
 6883        }
 6884      } else if (expr is MemberSelectExpr) {
 6885        var e = (MemberSelectExpr)expr;
 6886        if (e.Member.EnclosingClass is CoDatatypeDecl) {
 6887          int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel + 1;
 6888          CheckCoCalls(e.Obj, dl, coContext, coCandidates);
 6889          return;
 6890        }
 6891      } else if (expr is BinaryExpr) {
 6892        var e = (BinaryExpr)expr;
 6893        if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.EqCommon || e.ResolvedOp == BinaryExpr.ResolvedOpcode.NeqCommon) {
 6894          // Equality and disequality (for any type that may contain a co-datatype) are as destructive as can be--in ess
 6895          // they destruct the values indefinitely--so don't allow any co-recursive calls in the operands.
 6896          CheckCoCalls(e.E0, int.MaxValue, null, coCandidates);
 6897          CheckCoCalls(e.E1, int.MaxValue, null, coCandidates);
 6898          return;
 6899        }
 6900      } else if (expr is TernaryExpr) {
 6901        var e = (TernaryExpr)expr;
 6902        if (e.Op == TernaryExpr.Opcode.PrefixEqOp || e.Op == TernaryExpr.Opcode.PrefixNeqOp) {
 6903          // Prefix equality and disequality (for any type that may contain a co-datatype) are destructive.
 6904          CheckCoCalls(e.E0, int.MaxValue, null, coCandidates);
 6905          CheckCoCalls(e.E1, int.MaxValue, null, coCandidates);
 6906          CheckCoCalls(e.E2, int.MaxValue, null, coCandidates);
 6907          return;
 6908        }
 6909      } else if (expr is NestedMatchExpr) {
 6910        var e = (NestedMatchExpr)expr;
 6911        foreach (var child in e.SubExpressions) {
 6912          CheckCoCalls(child, destructionLevel, coContext, coCandidates);
 6913        }
 6914      } else if (expr is MatchExpr) {
 6915        var e = (MatchExpr)expr;
 6916        CheckCoCalls(e.Source, int.MaxValue, null, coCandidates);
 6917        foreach (var kase in e.Cases) {
 6918          CheckCoCalls(kase.Body, destructionLevel, coContext, coCandidates);
 6919        }
 6920        return;
 6921      } else if (expr is ITEExpr) {
 6922        var e = (ITEExpr)expr;
 6923        CheckCoCalls(e.Test, int.MaxValue, null, coCandidates);
 6924        CheckCoCalls(e.Thn, destructionLevel, coContext, coCandidates);
 6925        CheckCoCalls(e.Els, destructionLevel, coContext, coCandidates);
 6926        return;
 6927      } else if (expr is FunctionCallExpr) {
 6928        var e = (FunctionCallExpr)expr;
 6929        // First, consider the arguments of the call, making sure that they do not include calls within the recursive cl
 6930        // unless the callee is abstemious.
 6931        var abstemious = true;
 6932        if (!Attributes.ContainsBool(e.Function.Attributes, "abstemious", ref abstemious)) {
 6933          abstemious = false;
 6934        }
 6935        Contract.Assert(e.Args.Count == e.Function.Formals.Count);
 6936        for (var i = 0; i < e.Args.Count; i++) {
 6937          var arg = e.Args[i];
 6938          if (!e.Function.Formals[i].Type.IsCoDatatype) {
 6939            CheckCoCalls(arg, int.MaxValue, null, coCandidates);
 6940          } else if (abstemious) {
 6941            CheckCoCalls(arg, 0, coContext, coCandidates);
 6942          } else {
 6943            // don't you wish the callee were abstemious
 6944            CheckCoCalls(arg, int.MaxValue, null, coCandidates, e.Function);
 6945          }
 6946        }
 6947        // Second, investigate the possibility that this call itself may be a candidate co-call
 6948        if (e.Name != "requires" && ModuleDefinition.InSameSCC(currentFunction, e.Function)) {
 6949          // This call goes to another function in the same recursive cluster
 6950          if (destructionLevel != 0 && GuaranteedCoCtors(e.Function) <= destructionLevel) {
 6951            // a potentially destructive context
 6952            HasIntraClusterCallsInDestructiveContexts = true;  // this says we found an intra-cluster call unsuitable fo
 6953            if (!dealsWithCodatatypes) {
 6954              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6955            } else {
 6956              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseRecursiveCallsAreNotAllowedInThisContext;
 6957              if (functionYouMayWishWereAbstemious != null) {
 6958                e.CoCallHint = string.Format("perhaps try declaring function '{0}' with '{{:abstemious}}'", functionYouM
 6959              }
 6960            }
 6961          } else if (coContext == null) {
 6962            // no immediately enclosing co-constructor
 6963            if (!dealsWithCodatatypes) {
 6964              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6965            } else {
 6966              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseIsNotGuarded;
 6967            }
 6968          } else if (e.Function.Reads.Count != 0) {
 6969            // this call is disqualified from being a co-call, because of side effects
 6970            if (!dealsWithCodatatypes) {
 6971              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6972            } else {
 6973              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasSideEffects;
 6974            }
 6975          } else if (e.Function.Ens.Count != 0) {
 6976            // this call is disqualified from being a co-call, because it has a postcondition
 6977            // (a postcondition could be allowed, as long as it does not get to be used with
 6978            // co-recursive calls, because that could be unsound; for example, consider
 6979            // "ensures false")
 6980            if (!dealsWithCodatatypes) {
 6981              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6982            } else {
 6983              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasPostcondition;
 6984            }
 6985          } else {
 6986            // e.CoCall is not filled in here, but will be filled in when the list of candidates are processed
 6987            coCandidates.Add(new CoCallInfo(e, coContext));
 6988          }
 6989        }
 6990        return;
 6991      } else if (expr is LambdaExpr) {
 6992        var e = (LambdaExpr)expr;
 6993        CheckCoCalls(e.Term, destructionLevel, coContext, coCandidates);
 6994        if (e.Range != null) {
 6995          CheckCoCalls(e.Range, int.MaxValue, null, coCandidates);
 6996        }
 6997        foreach (var read in e.Reads) {
 6998          CheckCoCalls(read.E, int.MaxValue, null, coCandidates);
 6999        }
 7000        return;
 7001      } else if (expr is MapComprehension) {
 7002        var e = (MapComprehension)expr;
 7003        foreach (var ee in Attributes.SubExpressions(e.Attributes)) {
 7004          CheckCoCalls(ee, int.MaxValue, null, coCandidates);
 7005        }
 7006        if (e.Range != null) {
 7007          CheckCoCalls(e.Range, int.MaxValue, null, coCandidates);
 7008        }
 7009        // allow co-calls in the term
 7010        if (e.TermLeft != null) {
 7011          CheckCoCalls(e.TermLeft, destructionLevel, coContext, coCandidates);
 7012        }
 7013        CheckCoCalls(e.Term, destructionLevel, coContext, coCandidates);
 7014        return;
 7015      } else if (expr is OldExpr) {
 7016        var e = (OldExpr)expr;
 7017        // here, "coContext" is passed along (the use of "old" says this must be ghost code, so the compiler does not ne
 7018        CheckCoCalls(e.E, destructionLevel, coContext, coCandidates);
 7019        return;
 7020      } else if (expr is LetExpr) {
 7021        var e = (LetExpr)expr;
 7022        foreach (var rhs in e.RHSs) {
 7023          CheckCoCalls(rhs, int.MaxValue, null, coCandidates);
 7024        }
 7025        CheckCoCalls(e.Body, destructionLevel, coContext, coCandidates);
 7026        return;
 7027      } else if (expr is ApplyExpr) {
 7028        var e = (ApplyExpr)expr;
 7029        CheckCoCalls(e.Function, int.MaxValue, null, coCandidates);
 7030        foreach (var ee in e.Args) {
 7031          CheckCoCalls(ee, destructionLevel, null, coCandidates);
 7032        }
 7033        return;
 7034      }
 7035
 7036      // Default handling:
 7037      foreach (var ee in expr.SubExpressions) {
 7038        CheckCoCalls(ee, destructionLevel, null, coCandidates);
 7039      }
 7040    }
 7041
 7042    public static int GuaranteedCoCtors(Function function) {
 7043      Contract.Requires(function != null);
 7044      return function.Body != null ? GuaranteedCoCtorsAux(function.Body) : 0;
 7045    }
 7046
 7047    private static int GuaranteedCoCtorsAux(Expression expr) {
 7048      Contract.Requires(expr != null);
 7049      expr = expr.Resolved;
 7050      if (expr is DatatypeValue) {
 7051        var e = (DatatypeValue)expr;
 7052        if (e.Ctor.EnclosingDatatype is CoDatatypeDecl) {
 7053          var minOfArgs = int.MaxValue;  // int.MaxValue means: not yet encountered a formal whose type is a co-datatype
 7054          Contract.Assert(e.Arguments.Count == e.Ctor.Formals.Count);
 7055          for (var i = 0; i < e.Arguments.Count; i++) {
 7056            if (e.Ctor.Formals[i].Type.IsCoDatatype) {
 7057              var n = GuaranteedCoCtorsAux(e.Arguments[i]);
 7058              minOfArgs = Math.Min(minOfArgs, n);
 7059            }
 7060          }
 7061          return minOfArgs == int.MaxValue ? 1 : 1 + minOfArgs;
 7062        }
 7063      } else if (expr is ITEExpr) {
 7064        var e = (ITEExpr)expr;
 7065        var thn = GuaranteedCoCtorsAux(e.Thn);
 7066        var els = GuaranteedCoCtorsAux(e.Els);
 7067        return thn < els ? thn : els;
 7068      } else if (expr is NestedMatchExpr nestedMatchExpr) {
 7069        var childValues = nestedMatchExpr.Cases.Select(child => GuaranteedCoCtorsAux(child.Body)).ToList();
 7070        return childValues.Any() ? childValues.Min() : 0;
 7071      } else if (expr is MatchExpr) {
 7072        var e = (MatchExpr)expr;
 7073        var min = int.MaxValue;
 7074        foreach (var kase in e.Cases) {
 7075          var n = GuaranteedCoCtorsAux(kase.Body);
 7076          min = Math.Min(min, n);
 7077        }
 7078        return min == int.MaxValue ? 0 : min;
 7079      } else if (expr is LetExpr) {
 7080        var e = (LetExpr)expr;
 7081        return GuaranteedCoCtorsAux(e.Body);
 7082      } else if (expr is IdentifierExpr) {
 7083        var e = (IdentifierExpr)expr;
 7084        if (e.Type.IsCoDatatype && e.Var is Formal) {
 7085          // even though this is not a co-constructor, count this as 1, since that's what we would have done if it were,
 7086          return 1;
 7087        }
 7088      }
 7089      return 0;
 7090    }
 7091  }
 7092}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/TypeInferenceChecker.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using System.Diagnostics.Contracts;
 3using System.Linq;
 4using System.Numerics;
 5using Microsoft.Boogie;
 6using static Microsoft.Dafny.ErrorRegistry;
 7
 8namespace Microsoft.Dafny;
 9
 10partial class Resolver {
 11  class TypeInferenceCheckingContext : IASTVisitorContext {
 12    private readonly IASTVisitorContext astVisitorContext;
 13
 430714    public bool IsPrefixPredicate => astVisitorContext is PrefixPredicate;
 015    public bool IsExtremePredicate => astVisitorContext is ExtremePredicate;
 10419716    public bool IsPrefixDeclaration => astVisitorContext is PrefixPredicate or PrefixLemma;
 17
 1554618    public TypeInferenceCheckingContext(IASTVisitorContext astVisitorContext) {
 777319      this.astVisitorContext = astVisitorContext;
 777320    }
 21
 517822    ModuleDefinition IASTVisitorContext.EnclosingModule => astVisitorContext.EnclosingModule;
 23  }
 24
 25  class CheckTypeInferenceVisitor : ASTVisitor<TypeInferenceCheckingContext> {
 26    private readonly Resolver resolver;
 027    private ErrorReporter reporter => resolver.reporter;
 28
 177629    public CheckTypeInferenceVisitor(Resolver resolver) {
 88830      this.resolver = resolver;
 88831    }
 32
 777333    public override TypeInferenceCheckingContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostcon
 777334      return new TypeInferenceCheckingContext(astVisitorContext);
 777335    }
 36
 233337    protected override void VisitOneDeclaration(TopLevelDecl decl) {
 233338      if (decl is NewtypeDecl newtypeDecl) {
 039        if (newtypeDecl.Var != null) {
 040          if (!IsDetermined(newtypeDecl.BaseType.NormalizeExpand())) {
 041            reporter.Error(MessageSource.Resolver, newtypeDecl.tok, "newtype's base type is not fully determined; add an
 042              newtypeDecl.Var.Name);
 043          }
 044        }
 45
 294546      } else if (decl is SubsetTypeDecl subsetTypeDecl) {
 61247        if (!IsDetermined(subsetTypeDecl.Rhs.NormalizeExpand())) {
 048          reporter.Error(MessageSource.Resolver, subsetTypeDecl.tok,
 049            "subset type's base type is not fully determined; add an explicit type for '{0}'", subsetTypeDecl.Var.Name);
 050        }
 51
 286052      } else if (decl is DatatypeDecl datatypeDecl) {
 707753        foreach (var member in resolver.classMembers[datatypeDecl].Values) {
 265254          if (member is DatatypeDestructor dtor) {
 82055            var rolemodel = dtor.CorrespondingFormals[0];
 164056            for (var i = 1; i < dtor.CorrespondingFormals.Count; i++) {
 057              var other = dtor.CorrespondingFormals[i];
 058              if (!Type.Equal_Improved(rolemodel.Type, other.Type)) {
 059                reporter.Error(MessageSource.Resolver, other,
 060                  "shared destructors must have the same type, but '{0}' has type '{1}' in constructor '{2}' and type '{
 061                  rolemodel.Name, rolemodel.Type, dtor.EnclosingCtors[0].Name, other.Type, dtor.EnclosingCtors[i].Name);
 062              }
 063            }
 82064          }
 183265        }
 52766      }
 67
 233368      base.VisitOneDeclaration(decl);
 233369    }
 70
 30671    public override void VisitField(Field field) {
 30672      if (field is ConstantField constantField) {
 073        resolver.PartiallySolveTypeConstraints(true);
 074        CheckTypeIsDetermined(field.tok, field.Type, "const");
 075      }
 76
 30677      base.VisitField(field);
 30678    }
 79
 34742680    protected override bool VisitOneStatement(Statement stmt, TypeInferenceCheckingContext context) {
 34742681      if (stmt is CalcStmt calcStmt) {
 82        // The resolution of the calc statement builds up .Steps and .Result, which are of the form E0 OP E1, where
 83        // E0 and E1 are expressions from .Lines.  These additional expressions still need to have their .ResolvedOp
 84        // fields filled in, so we visit them, rather than just the parsed .Lines.
 085        Attributes.SubExpressions(calcStmt.Attributes).Iter(e => VisitExpression(e, context));
 086        calcStmt.Steps.Iter(e => VisitExpression(e, context));
 087        VisitExpression(calcStmt.Result, context);
 088        calcStmt.Hints.Iter(hint => VisitStatement(hint, context));
 089        return false; // we're done with all subcomponents of the CalcStmt
 90      }
 91
 34742692      return base.VisitOneStatement(stmt, context);
 34742693    }
 94
 34742695    protected override void PostVisitOneStatement(Statement stmt, TypeInferenceCheckingContext context) {
 44784696      if (stmt is VarDeclStmt) {
 10042097        var s = (VarDeclStmt)stmt;
 61385198        foreach (var local in s.Locals) {
 10419799          CheckTypeIsDetermined(local.Tok, local.Type, "local variable");
 104197100          CheckTypeArgsContainNoOrdinal(local.Tok, local.type, context);
 104197101        }
 347426102      } else if (stmt is VarDeclPattern) {
 0103        var s = (VarDeclPattern)stmt;
 0104        s.LocalVars.Iter(local => CheckTypeIsDetermined(local.Tok, local.Type, "local variable"));
 0105        s.LocalVars.Iter(local => CheckTypeArgsContainNoOrdinal(local.Tok, local.Type, context));
 106
 247006107      } else if (stmt is ForallStmt) {
 0108        var s = (ForallStmt)stmt;
 0109        s.BoundVars.Iter(bv => CheckTypeIsDetermined(bv.tok, bv.Type, "bound variable"));
 0110        s.BoundVars.Iter(bv => CheckTypeArgsContainNoOrdinal(bv.tok, bv.Type, context));
 111
 247006112      } else if (stmt is AssignSuchThatStmt) {
 0113        var s = (AssignSuchThatStmt)stmt;
 0114        foreach (var lhs in s.Lhss) {
 0115          CheckTypeArgsContainNoOrdinal(lhs.tok, lhs.Type, context);
 0116        }
 0117      }
 118
 347426119      base.PostVisitOneStatement(stmt, context);
 347426120    }
 121
 1779640122    protected override void PostVisitOneExpression(Expression expr, TypeInferenceCheckingContext context) {
 2311171123      if (expr is LiteralExpr) {
 531531124        var e = (LiteralExpr)expr;
 531531125        if (e.Type.IsBitVectorType || e.Type.IsBigOrdinalType) {
 0126          var n = (BigInteger)e.Value;
 0127          var absN = n < 0 ? -n : n;
 128          // For bitvectors, check that the magnitude fits the width
 0129          if (e.Type.IsBitVectorType && MaxBV(e.Type.AsBitVectorType.Width) < absN) {
 0130            resolver.reporter.Error(MessageSource.Resolver, e.tok, "literal ({0}) is too large for the bitvector type {1
 0131          }
 132          // For bitvectors and ORDINALs, check for a unary minus that, earlier, was mistaken for a negative literal
 133          // This can happen only in `match` patterns (see comment by LitPattern.OptimisticallyDesugaredLit).
 0134          if (n < 0 || e.tok.val == "-0") {
 0135            Contract.Assert(e.tok.val == "-0");  // this and the "if" above tests that "n < 0" happens only when the tok
 0136            resolver.reporter.Error(MessageSource.Resolver, e.tok, "unary minus (-{0}, type {1}) not allowed in case pat
 0137          }
 0138        }
 139
 538962140        if (expr is StaticReceiverExpr stexpr) {
 22293141          foreach (Type t in stexpr.Type.TypeArgs) {
 0142            if (t is InferredTypeProxy && ((InferredTypeProxy)t).T == null) {
 0143              resolver.reporter.Error(MessageSource.Resolver, stexpr.tok, "type of type parameter could not be determine
 0144            }
 0145          }
 7431146        }
 147
 1779640148      } else if (expr is ComprehensionExpr) {
 0149        var e = (ComprehensionExpr)expr;
 0150        foreach (var bv in e.BoundVars) {
 0151          if (!IsDetermined(bv.Type.Normalize())) {
 0152            resolver.reporter.Error(MessageSource.Resolver, bv.tok,
 0153              $"type of bound variable '{bv.Name}' could not be determined; please specify the type explicitly");
 0154          } else if (context.IsExtremePredicate) {
 0155            CheckContainsNoOrdinal(bv.tok, bv.Type, $"type of bound variable '{bv.Name}' ('{bv.Type}') is not allowed to
 0156          }
 0157        }
 158
 0159        if (e is ExistsExpr && e.Range == null) {
 0160          var binBody = ((ExistsExpr)e).Term as BinaryExpr;
 0161          if (binBody != null && binBody.Op == BinaryExpr.Opcode.Imp) {  // check Op, not ResolvedOp, in order to distin
 162                                                                         // apply the wisdom of Claude Marche: issue a w
 0163            resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0164              "the quantifier has the form 'exists x :: A ==> B', which most often is a typo for 'exists x :: A && B'; "
 0165              "if you think otherwise, rewrite as 'exists x :: (A ==> B)' or 'exists x :: !A || B' to suppress this warn
 0166          }
 0167        }
 168
 1271719169      } else if (expr is MemberSelectExpr) {
 23610170        var e = (MemberSelectExpr)expr;
 31041171        if (e.Member is Function || e.Member is Method) {
 7431172          var i = 0;
 35214173          foreach (var p in Util.Concat(e.TypeApplication_AtEnclosingClass, e.TypeApplication_JustMember)) {
 4307174            var tp = i < e.TypeApplication_AtEnclosingClass.Count
 4307175              ? e.Member.EnclosingClass.TypeArgs[i]
 4307176              : ((ICallable)e.Member).TypeArgs[i - e.TypeApplication_AtEnclosingClass.Count];
 4307177            if (!IsDetermined(p.Normalize())) {
 0178              resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0179                $"type parameter '{tp.Name}' (inferred to be '{p}') to the {e.Member.WhatKind} '{e.Member.Name}' could n
 8614180            } else if (!context.IsPrefixPredicate) { // this check is done in extreme predicates, so no need to repeat i
 4307181              CheckContainsNoOrdinal(e.tok, p,
 4307182                $"type parameter '{tp.Name}' (passed in as '{p}') to the {e.Member.WhatKind} '{e.Member.Name}' is not al
 4307183            }
 4307184            i++;
 4307185          }
 7431186        }
 1248109187      } else if (expr is FunctionCallExpr) {
 0188        var e = (FunctionCallExpr)expr;
 0189        var i = 0;
 0190        foreach (var p in Util.Concat(e.TypeApplication_AtEnclosingClass, e.TypeApplication_JustFunction)) {
 0191          var tp = i < e.TypeApplication_AtEnclosingClass.Count
 0192            ? e.Function.EnclosingClass.TypeArgs[i]
 0193            : e.Function.TypeArgs[i - e.TypeApplication_AtEnclosingClass.Count];
 0194          if (!IsDetermined(p.Normalize())) {
 0195            var hint = e.Name.StartsWith("reveal_")
 0196              ? ". If you are making an opaque function, make sure that the function can be called."
 0197              : "";
 0198            resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0199              $"type parameter '{tp.Name}' (inferred to be '{p}') in the function call to '{e.Name}' could not be determ
 0200          } else if (!context.IsPrefixPredicate) { // this check is done in extreme predicates, so no need to repeat it 
 0201            CheckContainsNoOrdinal(e.tok, p,
 0202              $"type parameter '{tp.Name}' (passed in as '{p}') to function call '{e.Name}' is not allowed to use ORDINA
 0203          }
 0204          i++;
 0205        }
 1224499206      } else if (expr is LetExpr) {
 0207        var e = (LetExpr)expr;
 0208        foreach (var p in e.LHSs) {
 0209          foreach (var x in p.Vars) {
 0210            if (!IsDetermined(x.Type.Normalize())) {
 0211              resolver.reporter.Error(MessageSource.Resolver, x.tok, $"the type of the bound variable '{x.Name}' could n
 0212            } else {
 0213              CheckTypeArgsContainNoOrdinal(x.tok, x.Type, context);
 0214            }
 0215          }
 0216        }
 1621467217      } else if (expr is IdentifierExpr) {
 218        // by specializing for IdentifierExpr, error messages will be clearer
 396968219        CheckTypeIsDetermined(expr.tok, expr.Type, "variable");
 1224499220      } else if (expr is ConversionExpr) {
 0221        var e = (ConversionExpr)expr;
 0222        if (e.ToType.IsRefType) {
 0223          var fromType = e.E.Type;
 0224          Contract.Assert(fromType.IsRefType);
 0225          if (fromType.IsSubtypeOf(e.ToType, false, true) || e.ToType.IsSubtypeOf(fromType, false, true)) {
 226            // looks good
 0227          } else {
 0228            resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0229              "a type cast to a reference type ({0}) must be from a compatible type (got {1}); this cast could never suc
 0230              e.ToType, fromType);
 0231          }
 0232        }
 827531233      } else if (expr is TypeTestExpr) {
 0234        var e = (TypeTestExpr)expr;
 0235        var fromType = e.E.Type;
 0236        if (fromType.IsSubtypeOf(e.ToType, false, true)) {
 237          // This test is allowed and it always returns true
 0238        } else if (!e.ToType.IsSubtypeOf(fromType, false, true)) {
 0239          resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0240            "a type test to '{0}' must be from a compatible type (got '{1}')", e.ToType, fromType);
 0241        } else if (!e.ToType.IsRefType) {
 0242          resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0243            "a non-trivial type test is allowed only for reference types (tried to test if '{1}' is a '{0}')", e.ToType,
 0244        }
 1654987245      } else if (CheckTypeIsDetermined(expr.tok, expr.Type, "expression")) {
 848550246        if (expr is UnaryOpExpr uop) {
 247          // The CheckTypeInference_Visitor has already visited uop.E, but uop.E's may be undetermined. If that happened
 248          // then an error has already been reported.
 42163249          if (CheckTypeIsDetermined(uop.E.tok, uop.E.Type, "expression")) {
 21069250            uop.ResolveOp(); // Force resolution eagerly at this point to catch potential bugs
 21069251          }
 977420252        } else if (expr is BinaryExpr) {
 149964253          var e = (BinaryExpr)expr;
 149964254          e.ResolvedOp = ResolveOp(e.Op, e.E0.Type, e.E1.Type);
 255          // Check for useless comparisons with "null"
 149964256          Expression other = null;  // if "null" if one of the operands, then "other" is the other
 149964257          if (e.E0 is LiteralExpr && ((LiteralExpr)e.E0).Value == null) {
 0258            other = e.E1;
 150576259          } else if (e.E1 is LiteralExpr && ((LiteralExpr)e.E1).Value == null) {
 612260            other = e.E0;
 612261          }
 150576262          if (other != null) {
 612263            bool sense = true;
 612264            switch (e.ResolvedOp) {
 265              case BinaryExpr.ResolvedOpcode.NeqCommon:
 612266                sense = false;
 612267                goto case BinaryExpr.ResolvedOpcode.EqCommon;
 612268              case BinaryExpr.ResolvedOpcode.EqCommon: {
 612269                  var nntUdf = other.Type.AsNonNullRefType;
 612270                  if (nntUdf != null) {
 0271                    string name = null;
 0272                    string hint = "";
 0273                    other = other.Resolved;
 0274                    if (other is IdentifierExpr) {
 0275                      name = $"variable '{((IdentifierExpr)other).Name}'";
 0276                    } else if (other is MemberSelectExpr) {
 0277                      var field = ((MemberSelectExpr)other).Member as Field;
 278                      // The type of the field may be a formal type parameter, in which case the hint is omitted
 0279                      if (field.Type.IsNonNullRefType) {
 0280                        name = $"field '{field.Name}'";
 0281                      }
 0282                    }
 0283                    if (name != null) {
 284                      // The following relies on that a NonNullTypeDecl has a .Rhs that is a
 285                      // UserDefinedType denoting the possibly null type declaration and that
 286                      // these two types have the same number of type arguments.
 0287                      var nonNullTypeDecl = (NonNullTypeDecl)nntUdf.ResolvedClass;
 0288                      var possiblyNullUdf = (UserDefinedType)nonNullTypeDecl.Rhs;
 0289                      var possiblyNullTypeDecl = (ClassDecl)possiblyNullUdf.ResolvedClass;
 0290                      Contract.Assert(nonNullTypeDecl.TypeArgs.Count == possiblyNullTypeDecl.TypeArgs.Count);
 0291                      Contract.Assert(nonNullTypeDecl.TypeArgs.Count == nntUdf.TypeArgs.Count);
 0292                      var ty = new UserDefinedType(nntUdf.tok, possiblyNullUdf.Name, possiblyNullTypeDecl, nntUdf.TypeAr
 293
 0294                      hint = $" (to make it possible for {name} to have the value 'null', declare its type to be '{ty}')
 0295                    }
 0296                    var b = sense ? "false" : "true";
 0297                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0298                      $"the type of the other operand is a non-null type, so this comparison with 'null' will always ret
 0299                  }
 612300                  break;
 301                }
 302              case BinaryExpr.ResolvedOpcode.NotInSet:
 303              case BinaryExpr.ResolvedOpcode.NotInSeq:
 304              case BinaryExpr.ResolvedOpcode.NotInMultiSet:
 0305                sense = false;
 0306                goto case BinaryExpr.ResolvedOpcode.InSet;
 307              case BinaryExpr.ResolvedOpcode.InSet:
 308              case BinaryExpr.ResolvedOpcode.InSeq:
 0309              case BinaryExpr.ResolvedOpcode.InMultiSet: {
 0310                  var ty = other.Type.NormalizeExpand();
 0311                  var what = ty is SetType ? "set" : ty is SeqType ? "seq" : "multiset";
 0312                  if (((CollectionType)ty).Arg.IsNonNullRefType) {
 0313                    var non = sense ? "" : "non-";
 0314                    var b = sense ? "false" : "true";
 0315                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0316                      $"the type of the other operand is a {what} of non-null elements, so the {non}inclusion test of 'n
 0317                  }
 0318                  break;
 319                }
 320              case BinaryExpr.ResolvedOpcode.NotInMap:
 0321                goto case BinaryExpr.ResolvedOpcode.InMap;
 0322              case BinaryExpr.ResolvedOpcode.InMap: {
 0323                  var ty = other.Type.NormalizeExpand();
 0324                  if (((MapType)ty).Domain.IsNonNullRefType) {
 0325                    var b = sense ? "false" : "true";
 0326                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0327                      $"the type of the other operand is a map to a non-null type, so the inclusion test of 'null' will 
 0328                  }
 0329                  break;
 330                }
 331              default:
 0332                break;
 333            }
 612334          }
 836167335        } else if (expr is NegationExpression) {
 29805336          var e = (NegationExpression)expr;
 29805337          Expression resolved = null;
 59610338          if (e.E is LiteralExpr lit) { // note, not e.E.Resolved, since we don't want to do this for double negations
 339                                        // For real-based types, integer-based types, and bi (but not bitvectors), "-" f
 340                                        // just a literal expression with a negative value
 50689341            if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 20884342              var d = (BaseTypes.BigDec)lit.Value;
 20884343              Contract.Assert(!d.IsNegative);
 20884344              resolved = new LiteralExpr(e.tok, -d);
 38726345            } else if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 8921346              var n = (BigInteger)lit.Value;
 8921347              Contract.Assert(0 <= n);
 8921348              resolved = new LiteralExpr(e.tok, -n);
 8921349            }
 29805350          }
 29805351          if (resolved == null) {
 352            // Treat all other expressions "-e" as "0 - e"
 353            Expression zero;
 0354            if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 0355              zero = new LiteralExpr(e.tok, BaseTypes.BigDec.ZERO);
 0356            } else {
 0357              Contract.Assert(e.E.Type.IsNumericBased(Type.NumericPersuasion.Int) || e.E.Type.IsBitVectorType);
 0358              zero = new LiteralExpr(e.tok, 0);
 0359            }
 0360            zero.Type = expr.Type;
 0361            resolved = new BinaryExpr(e.tok, BinaryExpr.Opcode.Sub, zero, e.E) { ResolvedOp = BinaryExpr.ResolvedOpcode.
 0362          }
 29805363          resolved.Type = expr.Type;
 29805364          e.ResolvedExpression = resolved;
 29805365        }
 827456366      }
 367
 1779640368      base.PostVisitOneExpression(expr, context);
 1779640369    }
 370
 8682371    protected override void VisitExtendedPattern(ExtendedPattern pattern, TypeInferenceCheckingContext context) {
 8682372      base.VisitExtendedPattern(pattern, context);
 373
 15636374      if (pattern is IdPattern { BoundVar: { } bv }) {
 6954375        CheckTypeIsDetermined(bv.Tok, bv.Type, "bound variable");
 6954376      }
 8682377    }
 378
 10945346379    public static bool IsDetermined(Type t) {
 380      Contract.Requires(t != null);
 381      Contract.Requires(!(t is TypeProxy) || ((TypeProxy)t).T == null);
 382      // all other proxies indicate the type has not yet been determined, provided their type parameters have been
 11288542383      return !(t is TypeProxy) && t.TypeArgs.All(tt => IsDetermined(tt.Normalize()));
 10945346384    }
 385
 888386    readonly ISet<TypeProxy> UnderspecifiedTypeProxies = new HashSet<TypeProxy>();
 387
 2454133388    public bool CheckTypeIsDetermined(IToken tok, Type t, string what) {
 389      Contract.Requires(tok != null);
 390      Contract.Requires(t != null);
 391      Contract.Requires(what != null);
 2454133392      t = t.NormalizeExpandKeepConstraints();
 393
 2454233394      if (t is TypeProxy) {
 100395        var proxy = (TypeProxy)t;
 135396        if (!UnderspecifiedTypeProxies.Contains(proxy)) {
 397          // report an error for this TypeProxy only once
 35398          resolver.reporter.Error(MessageSource.Resolver, tok, "the type of this {0} is underspecified", what);
 35399          UnderspecifiedTypeProxies.Add(proxy);
 35400        }
 100401        return false;
 402      }
 403      // Recurse on type arguments:
 3551422404      return t.TypeArgs.All(rg => CheckTypeIsDetermined(tok, rg, what));
 2454133405    }
 406
 104197407    public void CheckTypeArgsContainNoOrdinal(IToken tok, Type t, TypeInferenceCheckingContext context) {
 408      Contract.Requires(tok != null);
 409      Contract.Requires(t != null);
 104197410      if (context.IsPrefixDeclaration) {
 411        // User-provided expressions in extreme predicates/lemmas are checked in the extreme declarations, so need
 412        // need to do them here again for the prefix predicates/lemmas.
 104197413      } else {
 104197414        t = t.NormalizeExpand();
 197363415        t.TypeArgs.Iter(rg => CheckContainsNoOrdinal(tok, rg, "an ORDINAL type is not allowed to be used as a type argum
 104197416      }
 104197417    }
 418
 131613419    public void CheckContainsNoOrdinal(IToken tok, Type t, string errMsg) {
 420      Contract.Requires(tok != null);
 421      Contract.Requires(t != null);
 422      Contract.Requires(errMsg != null);
 131613423      t = t.NormalizeExpand();
 131613424      if (t.IsBigOrdinalType) {
 0425        resolver.reporter.Error(MessageSource.Resolver, tok, errMsg);
 0426      }
 165753427      t.TypeArgs.Iter(rg => CheckContainsNoOrdinal(tok, rg, errMsg));
 131613428    }
 429  }
 430}

Methods/Properties

get_AllowedToDependOnAllocationState()
get_Kind()
.ctor(Microsoft.Dafny.IASTVisitorContext)
.ctor(Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext,Microsoft.Dafny.LambdaExpr)
Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()
.ctor(Microsoft.Dafny.ErrorReporter)
GetContext(Microsoft.Dafny.IASTVisitorContext,System.Boolean)
VisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
VisitTopLevelFrameExpression(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
DesugarFunctionsInFrameClause(Microsoft.Dafny.FrameExpression)
FrameArrowToObjectSet(Microsoft.Dafny.Expression)
VisitExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
VisitOneExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
DiscoverBestBounds_MultipleVars(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverBestBounds_MultipleVars_AllowReordering(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverAllBounds_Aux_MultipleVars(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverAllBounds_SingleVar(VT,Microsoft.Dafny.Expression)
DiscoverAllBounds_Aux_SingleVar(System.Collections.Generic.List`1<VT>,System.Int32,Microsoft.Dafny.Expression,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>)
DiscoverBoundsFunctionCallExpr(Microsoft.Dafny.FunctionCallExpr,VT,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>)
NormalizedConjuncts()
SanitizeForBoundDiscovery(System.Collections.Generic.List`1<VT>,System.Int32,Microsoft.Dafny.BinaryExpr/ResolvedOpcode,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>,Microsoft.Dafny.Expression&,Microsoft.Dafny.Expression&)
IsMonotonic(Microsoft.Dafny.Expression,Microsoft.Dafny.IVariable,System.Boolean)
ResolveNamesAndInferTypes(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,System.Boolean)
ResolveNamesAndInferTypesForOneDeclarationInitial(Microsoft.Dafny.TopLevelDecl)
ResolveNamesAndInferTypesForOneDeclaration(Microsoft.Dafny.TopLevelDecl)
EagerAddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,System.String)
AddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression,System.String)
PrintTypeConstraintState(System.Int32)
SolveAllTypeConstraints()
ResolveAttributes(Microsoft.Dafny.IAttributeBearingDeclaration,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveTypeParameters(System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Boolean,Microsoft.Dafny.TypeParameter/ParentType)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,System.String,System.Object[])
ConstrainTypeExprBool(Microsoft.Dafny.Expression,System.String)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.IToken,System.String,System.Object[])
ConstrainAssignable(Microsoft.Dafny.NonProxyType,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean&,System.Boolean)
ConstrainAssignableTypeArgs(Microsoft.Dafny.Type,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean&)
ConstrainSubtypeRelation_Equal(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean,System.Boolean)
ConstrainSubtypeRelation_Aux(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint,System.Boolean,System.Boolean)
DetermineRootLeaf(Microsoft.Dafny.Type,System.Boolean&,System.Boolean&,System.Boolean&,System.Boolean&)
.ctor(Microsoft.Dafny.DafnyOptions)
AssignProxyAndHandleItsConstraints(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,System.Boolean)
AssignProxyAndHandleItsConstraints_aux(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,System.Boolean)
ImposeSubtypingConstraint(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ConstrainTypeHead_Recursive(Microsoft.Dafny.Type,Microsoft.Dafny.Type&)
ConstrainTypeHead(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
KeepConstraints(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
.ctor(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type[],Microsoft.Dafny.TypeConstraint/ErrorMsg)
ToString()
Confirm(Microsoft.Dafny.Resolver,System.Boolean,System.Boolean&,System.Boolean&)
ProxyWithNoSubTypeConstraint(Microsoft.Dafny.Type,Microsoft.Dafny.Resolver)
CouldBeAnything()
FindCollectionType(Microsoft.Dafny.DafnyOptions,Microsoft.Dafny.Type,System.Boolean,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
.ctor(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type[],Microsoft.Dafny.Expression[],Microsoft.Dafny.TypeConstraint/ErrorMsg)
.ctor(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Boolean,System.Boolean,Microsoft.Dafny.TypeConstraint/ErrorMsg)
PartiallySolveTypeConstraints(System.Boolean)
NewIntegerBasedProxy(Microsoft.Dafny.IToken)
ContainsAsTypeParameter(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
AddAllProxies(Microsoft.Dafny.Type,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
ProcessAssignable(Microsoft.Dafny.TypeProxy,System.Collections.Generic.List`1<Microsoft.Dafny.Type>)
ConvertAssignableToSubtypeConstraints(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
TightenUpEquatable(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
ProcessOneSubtypingConstraintAndItsSubs(Microsoft.Dafny.TypeConstraint,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeConstraint>,System.Boolean,System.Boolean&)
ProcessFullStrength_SubDirection(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean&)
ProcessFullStrength_SuperDirection(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean&)
AssignKnownEnd(Microsoft.Dafny.TypeProxy,System.Boolean,System.Boolean)
AssignKnownEndsFullstrength(Microsoft.Dafny.TypeProxy)
AssignKnownEndsFullstrength_SubDirection(Microsoft.Dafny.TypeProxy)
CloseOverAssignableRhss(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
HasApplicableNullableRefTypeConstraint(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
HasApplicableNullableRefTypeConstraint_SubDirection(Microsoft.Dafny.TypeProxy)
HasApplicableNullableRefTypeConstraint_SubDirection_aux(Microsoft.Dafny.TypeProxy,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
AssignKnownEndsFullstrength_SuperDirection(Microsoft.Dafny.TypeProxy)
Reaches(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Int32,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
Reaches_aux(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Int32,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
ResolveClassMemberBodiesInitial(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveClassMemberBodies(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveCtorTypes(Microsoft.Dafny.DatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>)
ResolveCtorSignature(Microsoft.Dafny.DatatypeCtor,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
AddDatatypeDependencyEdge(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Type,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
ResolveFrameExpressionTopLevel(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.FrameExpressionUse,Microsoft.Dafny.ICodeContext)
ResolveFrameExpression(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.FrameExpressionUse,Microsoft.Dafny.ResolutionContext)
ResolveIterator(Microsoft.Dafny.IteratorDecl)
CheckIsLvalue(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveBlockStatement(Microsoft.Dafny.BlockStmt,Microsoft.Dafny.ResolutionContext)
ResolveStatementWithLabels(Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveAlternatives(System.Collections.Generic.List`1<Microsoft.Dafny.GuardedAlternative>,Microsoft.Dafny.AlternativeLoopStmt,Microsoft.Dafny.ResolutionContext)
ResolveCallStmt(Microsoft.Dafny.CallStmt,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Type)
ResolveActualParameters(Microsoft.Dafny.ActualBindings,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.IToken,System.Object,Microsoft.Dafny.ResolutionContext,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Expression)
GetLocationInformation(Microsoft.Dafny.Formal,System.Int32,System.Int32,System.String)
ResolveDotSuffix_Type(Microsoft.Dafny.ExprDotName,Microsoft.Dafny.ResolutionContext,System.Boolean,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
CreateResolver_IdentifierExpr(Microsoft.Dafny.IToken,System.String,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.TopLevelDecl)
ResolveStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveLoopSpecificationComponents(System.Collections.Generic.List`1<Microsoft.Dafny.AttributedExpression>,Microsoft.Dafny.Specification`1<Microsoft.Dafny.Expression>,Microsoft.Dafny.Specification`1<Microsoft.Dafny.FrameExpression>,Microsoft.Dafny.ResolutionContext)
ResolveParameterDefaultValues(System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.ResolutionContext)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.ResolveTypeOptionEnum,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ICodeContext,Microsoft.Dafny.ResolveTypeOptionEnum,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ICodeContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
.ctor(Microsoft.Dafny.Type,Microsoft.Dafny.ExprDotName)
ResolveTypeLenient(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Boolean)
FillInTypeArguments(Microsoft.Dafny.IToken,System.Int32,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,Microsoft.Dafny.Resolver/ResolveTypeOption)
TypeConstraintsIncludeProxy(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy)
TypeConstraintsIncludeProxy_Aux(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
ResolveTypeRhs(Microsoft.Dafny.TypeRhs,Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveMember(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String,Microsoft.Dafny.NonProxyType&)
PartiallyResolveTypeForMemberSelection(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String,System.Int32)
GetBaseTypeFromProxy(Microsoft.Dafny.TypeProxy,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetBaseTypeFromProxy_Eq(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetBaseTypeFromProxy_EqAux(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetRelatedTypeProxies(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
JoinOfAllSubtypes(Microsoft.Dafny.Type,Microsoft.Dafny.Type&,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
MeetOfAllSupertypes(Microsoft.Dafny.Type,Microsoft.Dafny.Type&,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean)
CheckVariance(Microsoft.Dafny.Type,Microsoft.Dafny.ICallable,Microsoft.Dafny.TypeParameter/TPVariance,System.Boolean)
ConstrainToIntegerType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ResolveDatatypeUpdate(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.DatatypeDecl,System.Collections.Generic.List`1<System.Tuple`3<Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Expression>>,Microsoft.Dafny.ResolutionContext,System.Collections.Generic.List`1<Microsoft.Dafny.MemberDecl>&,System.Collections.Generic.List`1<Microsoft.Dafny.DatatypeCtor>&)
DesugarDatatypeUpdate(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.DatatypeDecl,System.Collections.Generic.List`1<Microsoft.Dafny.DatatypeCtor>,System.Collections.Generic.Dictionary`2<System.String,System.Tuple`3<Microsoft.Dafny.BoundVar,Microsoft.Dafny.IdentifierExpr,Microsoft.Dafny.Expression>>,Microsoft.Dafny.ResolutionContext)
ResolveNameSegment(Microsoft.Dafny.NameSegment,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Boolean)
ResolveNameSegment(Microsoft.Dafny.NameSegment,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Boolean,Microsoft.Dafny.ModuleDecl&)
ResolveDatatypeConstructor(Microsoft.Dafny.NameSegment,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Tuple`2<Microsoft.Dafny.DatatypeCtor,System.Boolean>,System.String,Microsoft.Dafny.Expression&,Microsoft.Dafny.Expression&)
ResolveNameSegment_Type(Microsoft.Dafny.NameSegment,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveDotSuffix(Microsoft.Dafny.ExprDotName,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean)
CheckForAmbiguityInShadowedImportedModule(Microsoft.Dafny.ModuleDecl,System.String,Microsoft.Dafny.IToken,System.Boolean,System.Boolean)
NameConflictsWithModuleContents(Microsoft.Dafny.ModuleDecl,System.String,System.Boolean,System.Boolean)
ResolveExprDotCall(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.Type,Microsoft.Dafny.MemberDecl,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveApplySuffix(Microsoft.Dafny.ApplySuffix,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveDatatypeValue(Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.DatatypeValue,Microsoft.Dafny.DatatypeDecl,Microsoft.Dafny.Type,System.Boolean)
ResolveFunctionCallExpr(Microsoft.Dafny.FunctionCallExpr,Microsoft.Dafny.ResolutionContext)
ResolveReceiver(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveSeqSelectExpr(Microsoft.Dafny.SeqSelectExpr,Microsoft.Dafny.ResolutionContext)
get_Options()
.ctor(Microsoft.Dafny.DafnyOptions)
get_Reporter()
get_TypeConstraintErrorsToBeReported()
RevealedInScope(Microsoft.Dafny.Declaration)
VisibleInScope(Microsoft.Dafny.Declaration)
FreshTempVarName(System.String,Microsoft.Dafny.ICodeContext)
Create(Microsoft.Dafny.ModuleDefinition,Thing,Thing,System.Collections.Generic.IEqualityComparer`1<Thing>,System.Collections.Generic.ISet`1<Thing>&)
Name(System.Collections.Generic.ISet`1<Thing>,System.Func`2<Thing,System.String>)
ModuleNames(Microsoft.Dafny.Resolver/IAmbiguousThing`1<Thing>,System.Func`2<Thing,System.String>)
Create(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.TopLevelDecl)
Equals(Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.TopLevelDecl)
GetHashCode(Microsoft.Dafny.TopLevelDecl)
get_WhatKind()
.ctor(Microsoft.Dafny.ModuleDefinition,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.TopLevelDecl>)
Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.TopLevelDecl>.get_Pool()
ModuleNames()
Create(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.MemberDecl,Microsoft.Dafny.MemberDecl)
Equals(Microsoft.Dafny.MemberDecl,Microsoft.Dafny.MemberDecl)
GetHashCode(Microsoft.Dafny.MemberDecl)
get_WhatKind()
.ctor(Microsoft.Dafny.ModuleDefinition,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.MemberDecl>)
Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.MemberDecl>.get_Pool()
ModuleNames()
.ctor(Microsoft.Dafny.Program)
AddRotateMember(Microsoft.Dafny.ValuetypeDecl,System.String,Microsoft.Dafny.Type)
ObjectInvariant()
AsValuetypeDecl(Microsoft.Dafny.Type)
CheckDupModuleNames(Microsoft.Dafny.Program)
ResolveProgram(Microsoft.Dafny.Program)
ResolveValuetypeDecls()
ResolveModuleDefinition(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature,System.Boolean)
ResolveModuleExport(Microsoft.Dafny.LiteralModuleDecl,Microsoft.Dafny.ModuleSignature)
CheckModuleExportConsistency(Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.Resolver/ModuleBindings)
BindName(System.String,Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings)
TryLookup(Microsoft.Dafny.IToken,Microsoft.Dafny.ModuleDecl&)
TryLookupFilter(Microsoft.Dafny.IToken,Microsoft.Dafny.ModuleDecl&,System.Func`2<Microsoft.Dafny.ModuleDecl,System.Boolean>)
get_ModuleList()
SubBindings(System.String)
BindModuleNames(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings)
ShortenPrefix(System.Tuple`2<System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.LiteralModuleDecl>)
BindModuleName_LiteralModuleDecl(Microsoft.Dafny.LiteralModuleDecl,System.Collections.Generic.List`1<System.Tuple`2<System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.LiteralModuleDecl>>,Microsoft.Dafny.Resolver/ModuleBindings)
ResolveQualifiedModuleIdRootRefines(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ResolveQualifiedModuleIdRootImport(Microsoft.Dafny.AliasModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ResolveQualifiedModuleIdRootAbstract(Microsoft.Dafny.AbstractModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ProcessDependenciesDefinition(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.Graph`1<Microsoft.Dafny.ModuleDecl>)
ProcessDependencies(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.Graph`1<Microsoft.Dafny.ModuleDecl>)
ModuleNotFoundErrorMessage(System.Int32,System.Collections.Generic.List`1<Microsoft.Dafny.Name>,System.String)
EquivIfPresent(System.Collections.Generic.Dictionary`2<T1,T2>,T1,T2)
MergeSignature(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleSignature)
ResolveOpenedImports(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleDefinition,System.Boolean,Microsoft.Dafny.Resolver)
ResolveAlias(Microsoft.Dafny.TopLevelDecl)
ResolveOpenedImportsWorker(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDecl,System.Collections.Generic.HashSet`1<Microsoft.Dafny.ModuleSignature>,System.Boolean,Microsoft.Dafny.TopLevelDecl&)
RegisterTopLevelDecls(Microsoft.Dafny.ModuleDefinition,System.Boolean)
RegisterMembers(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.TopLevelDeclWithMembers,System.Collections.Generic.Dictionary`2<System.String,Microsoft.Dafny.MemberDecl>)
RegisterByMethod(Microsoft.Dafny.Function,Microsoft.Dafny.TopLevelDeclWithMembers)
MakeAbstractSignature(Microsoft.Dafny.ModuleSignature,System.String,System.Int32,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature>,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDefinition>)
CloneDeclaration(Microsoft.Dafny.VisibilityScope,Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.ModuleDefinition,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature>,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDefinition>)
ResolveModuleQualifiedId(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ErrorReporter)
ResolveExport(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleQualifiedId,System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.ModuleSignature&,Microsoft.Dafny.ErrorReporter)
RevealAllInScope(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.VisibilityScope)
ResolveTopLevelDecls_Signatures(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature,System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>)
.cctor()
ResolveTopLevelDecls_Core(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>,System.String,System.Boolean)
FillInPostConditionsAndBodiesOfPrefixLemmas(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>)
CheckIsOkayWithoutRHS(Microsoft.Dafny.ConstantField)
ResolveClassMembers_Pass1(Microsoft.Dafny.TopLevelDeclWithMembers)
CheckForUnnecessaryEqualitySupportDeclarations(Microsoft.Dafny.MemberDecl,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
CheckParameterDefaultValuesAreCompilable(System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.ICodeContext)
ReportCallGraphCycleError(Microsoft.Dafny.ICallable,System.String)
ReportCycleError(System.Collections.Generic.List`1<X>,System.Func`2<X,Microsoft.Dafny.IToken>,System.Func`2<X,System.String>,System.String)
MaxBV(Microsoft.Dafny.Type)
MaxBV(System.Int32)
FigureOutNativeType(Microsoft.Dafny.NewtypeDecl)
CheckOlderParameters(Microsoft.Dafny.Function)
CheckExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
CheckExpression(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
VisitOneExpr(Microsoft.Dafny.Expression)
VisitOneStmt(Microsoft.Dafny.Statement)
CheckForFuelAdjustments(Microsoft.Dafny.IToken,Microsoft.Dafny.Attributes,Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/FuelAdjustment_Context&)
Invert(Microsoft.Dafny.Resolver/CallingPosition)
.ctor(Microsoft.Dafny.Resolver,System.Boolean,System.Boolean)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
KNatMismatchError(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.ExtremePredicate/KType,Microsoft.Dafny.ExtremePredicate/KType)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ExtremePredicate)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
VisitOneStmt(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/CallingPosition&)
ExtremePredicateChecks(Microsoft.Dafny.Expression,Microsoft.Dafny.ExtremePredicate,Microsoft.Dafny.Resolver/CallingPosition)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ExtremeLemma)
VisitOneStmt(Microsoft.Dafny.Statement)
VisitOneExpr(Microsoft.Dafny.Expression)
ExtremeLemmaChecks(Microsoft.Dafny.Statement,Microsoft.Dafny.ExtremeLemma)
ExtremeLemmaChecks(Microsoft.Dafny.Expression,Microsoft.Dafny.ExtremeLemma)
CheckTypeCharacteristics_Stmt(Microsoft.Dafny.Statement,System.Boolean)
CheckTypeCharacteristics_Expr(Microsoft.Dafny.Expression,System.Boolean)
CheckTypeCharacteristics_Type(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement,System.Boolean&)
VisitOneExpr(Microsoft.Dafny.Expression,System.Boolean&)
VisitType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean)
CheckTypeInstantiation(Microsoft.Dafny.IToken,System.String,System.String,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Boolean)
CheckCharacteristics(Microsoft.Dafny.TypeParameter/TypeParameterCharacteristics,Microsoft.Dafny.Type,System.Boolean,System.String&,System.String&)
TypeEqualityErrorMessageHint(Microsoft.Dafny.Type)
CanCompareWith(Microsoft.Dafny.Expression)
ComputeGhostInterest(Microsoft.Dafny.Statement,System.Boolean,System.String,Microsoft.Dafny.ICodeContext)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ICallable)
VisitOneStmt(Microsoft.Dafny.Statement)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement)
.ctor(Microsoft.Dafny.Resolver)
CheckInit(System.Collections.Generic.List`1<Microsoft.Dafny.Statement>)
CheckInit(Microsoft.Dafny.Statement)
VisitExpr(Microsoft.Dafny.Expression)
VisitOneExpr(Microsoft.Dafny.Expression,System.Int32&)
LiberalRHSVisit(Microsoft.Dafny.Expression)
IsThisDotField(Microsoft.Dafny.MemberSelectExpr)
IsCollectionOperator(Microsoft.Dafny.BinaryExpr/ResolvedOpcode)
InferRequiredEqualitySupport(Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type)
ResolveParentTraitTypes(Microsoft.Dafny.TopLevelDeclWithMembers,Microsoft.Dafny.Graph`1<Microsoft.Dafny.TopLevelDeclWithMembers>)
RegisterInheritedMembers(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveClassMemberTypes(Microsoft.Dafny.TopLevelDeclWithMembers)
InheritedTraitMembers(Microsoft.Dafny.TopLevelDeclWithMembers)
CheckOverride_FunctionParameters(Microsoft.Dafny.Function,Microsoft.Dafny.Function,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_MethodParameters(Microsoft.Dafny.Method,Microsoft.Dafny.Method,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_TypeParameters(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.String,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_ResolvedParameters(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,System.String,System.String,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
SccStratosphereCheck(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
ComputeGroundingCtor(Microsoft.Dafny.IndDatatypeDecl)
CheckCanBeConstructed(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeParameter>)
DetermineEqualitySupport(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
IsRecognizedAttribute(Microsoft.Dafny.UserSuppliedAttributes,Microsoft.Dafny.IAttributeBearingDeclaration)
ScopePushAndReport(Microsoft.Dafny.Scope`1<Microsoft.Dafny.IVariable>,Microsoft.Dafny.IVariable,System.String)
ScopePushAndReport(Microsoft.Dafny.Scope`1<Thing>,System.String,Thing,Microsoft.Dafny.IToken,System.String)
ResolveFunctionSignature(Microsoft.Dafny.Function)
DisallowNonGhostFieldSpecifiers(Microsoft.Dafny.FrameExpression)
ResolveMethodSignature(Microsoft.Dafny.Method)
ResolveIteratorSignature(Microsoft.Dafny.IteratorDecl)
ObjectInvariant()
.ctor(Microsoft.Dafny.ResolveTypeOptionEnum)
.ctor(Microsoft.Dafny.TypeParameter/ParentType)
ResolvedArrayType(Microsoft.Dafny.IToken,System.Int32,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,System.Boolean)
FillInDefaultLoopDecreases(Microsoft.Dafny.LoopStmt,Microsoft.Dafny.Expression,System.Collections.Generic.List`1<Microsoft.Dafny.Expression>,Microsoft.Dafny.ICallable)
VarDotMethod(Microsoft.Dafny.IToken,System.String,System.String)
makeTemp(System.String,Microsoft.Dafny.AssignOrReturnStmt,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Expression)
EnsureSupportsErrorHandling(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean,System.Boolean)
CheckLocalityUpdates(Microsoft.Dafny.Statement,System.Collections.Generic.ISet`1<Microsoft.Dafny.LocalVariable>,System.String)
CheckLocalityUpdatesLhs(Microsoft.Dafny.Expression,System.Collections.Generic.ISet`1<Microsoft.Dafny.LocalVariable>,System.String)
.ctor(Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
ToString()
FindAllMembers(Microsoft.Dafny.ClassDecl,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.MemberDecl>)
GetThisType(Microsoft.Dafny.IToken,Microsoft.Dafny.TopLevelDeclWithMembers)
GetReceiverType(Microsoft.Dafny.IToken,Microsoft.Dafny.MemberDecl)
ResolveDominatingLabelInExpr(Microsoft.Dafny.IToken,System.String,System.String,Microsoft.Dafny.ResolutionContext)
VarDotFunction(Microsoft.Dafny.IToken,System.String,System.String)
LetPatIn(Microsoft.Dafny.IToken,Microsoft.Dafny.CasePattern`1<Microsoft.Dafny.BoundVar>,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression)
LetVarIn(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression)
ResolveLetOrFailExpr(Microsoft.Dafny.LetOrFailExpr,Microsoft.Dafny.ResolutionContext)
SelectAppropriateArrowTypeForFunction(Microsoft.Dafny.Function,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.BuiltIns)
SelectAppropriateArrowType(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.Type,System.Boolean,System.Boolean,Microsoft.Dafny.BuiltIns)
ConstrainToIntegerType(Microsoft.Dafny.Expression,System.Boolean,System.String)
ResolveNestedMatchExpr(Microsoft.Dafny.NestedMatchExpr,Microsoft.Dafny.ResolutionContext)
ResolveCasePattern(Microsoft.Dafny.CasePattern`1<VT>,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext)
FillInDefaultValueExpressions()
FillInDefaultValueExpression(Microsoft.Dafny.DefaultValueExpression,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.DefaultValueExpression,Microsoft.Dafny.Resolver/WorkProgress>)
.ctor(Microsoft.Dafny.Resolver,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.DefaultValueExpression,Microsoft.Dafny.Resolver/WorkProgress>,Microsoft.Dafny.Expression,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.IVariable,Microsoft.Dafny.Expression>,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
Substitute(Microsoft.Dafny.Expression)
BuildTypeArgumentSubstitute(System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Type)
AddParentTypeParameterSubstitutions(System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Type)
GhostPrefix(System.Boolean)
GetSignatureExt(Microsoft.Dafny.ModuleSignature,System.Boolean)
GetSignature(Microsoft.Dafny.ModuleSignature)
GetImpliedTypeConstraint(Microsoft.Dafny.IVariable,Microsoft.Dafny.Type)
GetImpliedTypeConstraint(Microsoft.Dafny.Expression,Microsoft.Dafny.Type)
FreeVariables(Microsoft.Dafny.Expression)
.cctor()
get_Msg()
.ctor(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type)
ResolveOp(Microsoft.Dafny.BinaryExpr/Opcode,Microsoft.Dafny.Type,Microsoft.Dafny.Type)
CollectFriendlyCallsInExtremeLemmaSpecification(Microsoft.Dafny.Expression,System.Boolean,System.Collections.Generic.ISet`1<Microsoft.Dafny.Expression>,System.Boolean,Microsoft.Dafny.ExtremeLemma)
.ctor(Microsoft.Dafny.Resolver,System.Collections.Generic.ISet`1<Microsoft.Dafny.Expression>,System.Boolean,Microsoft.Dafny.ExtremeLemma)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
get_IsPrefixPredicate()
get_IsExtremePredicate()
get_IsPrefixDeclaration()
.ctor(Microsoft.Dafny.IASTVisitorContext)
Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()
get_reporter()
.ctor(Microsoft.Dafny.Resolver)
GetContext(Microsoft.Dafny.IASTVisitorContext,System.Boolean)
VisitOneDeclaration(Microsoft.Dafny.TopLevelDecl)
VisitField(Microsoft.Dafny.Field)
VisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
PostVisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
PostVisitOneExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
VisitExtendedPattern(Microsoft.Dafny.ExtendedPattern,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
IsDetermined(Microsoft.Dafny.Type)
CheckTypeIsDetermined(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String)
CheckTypeArgsContainNoOrdinal(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
CheckContainsNoOrdinal(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String)